views:

352

answers:

5

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!

A: 

I might have misunderstood, but can't you simply:

static ExType TestException<ExType>(string message) where ExType:Exception
{
    return new ExType(message);
}
Vegard Larsen
+1  A: 

Have you tried, instead:

static T TestException<Exception>(string message)
{}

because I have a feeling that putting in the generic constraint is not necessary as all throwable exceptions must inherit from System.Exception anyway.

Remember that generics do accept inherited types.

Jon Limjap
A: 

I think seeing as all exceptions should have a parameterless constructor, and have the Message property, so the following should work:

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

Edit: OK, Message is read only, so you'll have to hope the class implements the Exception(string) constructor instead.

static ExType TestException<ExType>(string message) where ExType:Exception
{
    return new ExType(message);
}
samjudson
+3  A: 

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.

Matt Hamilton
+1  A: 

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();
    }
}
samjudson