Reputation: 899
Recently I came across the problem of creating an exception with a given message from within a generic method. For instance, the following code works as expected:
public static void Throw<T>() where T : Exception, new()
{
throw new T();
}
...
public static void Main()
{
Throw<ArgumentOutOfRangeException>(); // Throws desired exception but with a generic message.
}
However, I would like to be able to write
public static void Throw<T>(string message) where T : Exception, new()
{
T newException = new T();
newException.Message = message; // Not allowed. 'Message' is read-only.
throw newException;
}
...
public static void Main()
{
Throw<ArgumentOutOfRangeException>("You must specify a non-negative integer."); // Throws desired exception.
}
Is there any way of achieving this without the use of reflection either to change the value of the Message
property or dinamically activate an instance of the type with the desired parameters?
Upvotes: 2
Views: 3622
Reputation: 6281
You can use Activator.CreateInstance(typeof(T), "MyException description")
to enable a custom message.
There is no way to create the instance of some types ( see below ) without the use of the reflection or the use of the activator.
With newer .NET you can use factory interfaces, this of course will only work on custom exceptions as the interface needs to be implemented by the exception.
public interface IExceptionFactory<TSelf>
where TSelf : Exception, IExceptionFactory<TSelf>
{
static abstract TSelf Create(string message);
}
public T CreateException<T>(string message)
where T : Exception, IExceptionFactory<T>
{
return T.Create(message);
}
http://msdn.microsoft.com/de-de/library/wcxyzt4d(v=vs.80).aspx
Upvotes: 8
Reputation: 38179
The new constraint is only valid for default (parameterless) constructors, try this instead:
public static void Throw<T>(string message) where T : Exception
{
System.Reflection.ConstructorInfo constructor = typeof(T).GetConstructor(new Type[] { typeof(string) });
T newException = (T)constructor.Invoke(new object[] { message });
throw newException;
}
(note that you don't need the new constraint in this case)
Upvotes: 3