Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asking a Generic Method to Throw Specific Exception Type on FAIL

Right, I know I am totally going to look an idiot with this one, but my brain is just not kicking in to gear this morning.

I want to have a method where I can say "if it goes bad, come back with this type of Exception", right?

For example, something like (and this doesn't work):

    static ExType TestException<ExType>(string message) where ExType:Exception
    {
        Exception ex1 = new Exception();
        ExType ex = new Exception(message);
        return ex;
    }

Now whats confusing me is that we KNOW that the generic type is going to be of an Exception type due to the where clause. However, the code fails because we cannot implicitly cast Exception to ExType. We cannot explicitly convert it either, such as:

    static ExType TestException<ExType>(string message) where ExType:Exception
    {
        Exception ex1 = new Exception();
        ExType ex = (ExType)(new Exception(message));
        return ex;
    }

As that fails too.. So is this kind of thing possible? I have a strong feeling its going to be real simple, but I am having a tough day with the old noggin, so cut me some slack :P


Update

Thanks for the responses guys, looks like it wasn't me being a complete idiot! ;)

OK, so Vegard and Sam got me on to the point where I could instantiate the correct type, but then obviously got stuck because the message param is read-only following instantiation.

Matt hit the nail right on the head with his response, I have tested this and all works fine. Here is the example code:

    static ExType TestException<ExType>(string message) where ExType:Exception, new ()
    {
        ExType ex = (ExType)Activator.CreateInstance(typeof(ExType), message);
        return ex;
    }

Sweet! :)

Thanks guys!

like image 558
Rob Cooper Avatar asked Sep 03 '08 10:09

Rob Cooper


3 Answers

You can almost do it like this:

static void TestException<E>(string message) where E : Exception, new()
{
    var e = new E();
    e.Message = message;
    throw e;
}

However, that doesn't compile because Exception.Message is read only. It can only be assigned by passing it to the constructor, and there's no way to constrain a generic type with something other than a default constructor.

I think you'd have to use reflection (Activator.CreateInstance) to "new up" the custom exception type with the message parameter, like this:

static void TestException<E>(string message) where E : Exception
{
    throw Activator.CreateInstance(typeof(E), message) as E;
}

Edit Oops just realised you're wanting to return the exception, not throw it. The same principle applies, so I'll leave my answer as-is with the throw statements.

like image 189
Matt Hamilton Avatar answered Oct 21 '22 02:10

Matt Hamilton


The only issue with the solution is that it is possible to create a subclass of Exception which does not implement a constructor with a single string parameter, so the MethodMissingException might be thrown.

static void TestException<E>(string message) where E : Exception, new()
{
    try 
    {
      return Activator.CreateInstance(typeof(E), message) as E;
    } 
    catch(MissingMethodException ex) 
    {
      return new E();
    }
}
like image 25
samjudson Avatar answered Oct 21 '22 02:10

samjudson


I have been instantiating inline the type of exception I want to throw, like this:

if (ItemNameIsValid(ItemName, out errorMessage))
    throw new KeyNotFoundException("Invalid name '" + ItemName + "': " + errorMessage);
if (null == MyArgument)
    throw new ArgumentNullException("MyArgument is null");
like image 30
MiloNC Avatar answered Oct 21 '22 02:10

MiloNC