Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Ambiguous Match Found" when dynamically throwing "System.ArgumentException"

Consider this function:

static void Throw<T>(string message) where T : Exception
{
    throw (T)Activator.CreateInstance(typeof(T), message, (Exception)null);
}

Given a type T of System.ArgumentException, as the question title says, I get a runtime error of "Ambiguous Match Found". Looking at the documentation for ArgumentException, the following are the public constructors:

ArgumentException()
ArgumentException(string)
ArgumentException(SerializationInfo, StreamingContext)
ArgumentException(string, Exception)
ArgumentException(string, string)
ArgumentException(string, string, Exception)

Given I am passing 2 arguments in to CreateInstance, and forcing the null to be a null Exception, I am struggling to understand why it is not matching the 4th constructor in the above list?

like image 969
Moo-Juice Avatar asked Apr 20 '26 12:04

Moo-Juice


2 Answers

That will work:

static void Throw<T>(String message) 
  where T: Exception { // <- It's a good style to restrict T here

  throw (T) typeof(T).GetConstructor(new Type[] {typeof(String)}).Invoke(new Object[] {message});
}

Typical Exception has 4 or more constructors, so we'd rather point out which one we want to execute. Often, we have to check if there's a suitable constructor:

static void Throw<T>(String message) 
  where T: Exception { // <- It's a good style to restrict T here

  // The best constructor we can find
  ConstructorInfo ci = typeof(T).GetConstructor(new Type[] {typeof(String)});

  if (!Object.ReferenceEquals(null, ci))
    throw (T) ci.Invoke(new Object[] {message});

  // The second best constructor
  ci = typeof(T).GetConstructor(new Type[] {typeof(String), typeof(Exception)}); 

  if (!Object.ReferenceEquals(null, ci))
    throw (T) ci.Invoke(new Object[] {message, null});
  ...
}

However, in your case you can put it with Activator:

static void Throw<T>(String message) 
  where T: Exception { // <- It's a good style to restrict T here

  throw (T) Activator.CreateInstance(typeof(T), message);
}
like image 131
Dmitry Bychenko Avatar answered Apr 23 '26 02:04

Dmitry Bychenko


This might work

static void Throw<T>(string message)
{
    Exception ex = null;
    throw (Exception)Activator.CreateInstance(typeof(T), message, ex);
}

I don't know where Exception is on this list, but my guess is it is as specific as string, otherwise there wouldn't be a problem. How does the method overload resolution system decide which method to call when a null value is passed?

like image 35
Robert Fricke Avatar answered Apr 23 '26 01:04

Robert Fricke



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!