The above block refering to another question+answer on SO does NOT contain a correct answer which applies here!
I have a method used for unit testing. The purpose of this method is to ensure that a piece of code (refered to by a delegate) will throw a specific exception. If that exception is thrown, the unit test succeeds. If no exception is thrown or another type exception is thrown, the unit test will fail.
/// <summary>
/// Checks to make sure that the action throws a exception of type TException.
/// </summary>
/// <typeparam name="TException">The type of exception expected.</typeparam>
/// <param name="action">The code to execute which is expected to generate the exception.</param>
public static void Throws<TException>(Action action)
where TException : Exception
{
try
{
action();
}
catch (TException)
{
return;
}
catch (Exception ex)
{
Assert.Fail("Wrong exception was thrown. Exception of type " + ex.GetType() + " was thrown, exception of type " + typeof(TException) + " was expected.");
}
Assert.Fail("No exception was thrown. Exception of type " + typeof(TException) + " was expected.");
}
The next call should succeed, but it fails:
int result = 0;
Throws<DivideByZeroException>(() => result = result / result);
When the expected exception of type TException
is thrown, it is always caught by the second catch, not by the first catch. Why is this?
Of course I can use a workarround with one catch and test if ex
is of type TException
. By I simply want to know/understand why this code compiles but simple (never?) works.
EDIT
At request a "working" demo:
using System;
namespace GenericExceptionDemo
{
class Program
{
static void Main(string[] args)
{
int n = 0;
Catch<DivideByZeroException>(() => n = n / n);
}
static public void Catch<TException>(Action action)
where TException: Exception
{
try
{
action();
Console.WriteLine("No exception thrown. !!!Fail!!!");
}
catch (TException)
{
Console.WriteLine("Expected exception thrown. PASS!");
}
catch(Exception ex)
{
Console.WriteLine("An unexpected exception of type " + ex.GetType() + " thrown. !!!FAIL!!!");
}
}
}
}
Don't catch generic Exceptions While this seems harmless, some unintended side effects could result. For example, if className() is null, Class. forName() will throw a NullPointerException , which will be caught in the method.
The generic exception handler can handle all the exceptions but you should place is at the end, if you place it at the before all the catch blocks then it will display the generic message. You always want to give the user a meaningful message for each type of exception rather then a generic message.
It refers to exception class that is near the top of the exception class hierarchy. Note that an exception class cannot be a generic class ... in the Java sense of generic types. The JLS says: "Note that a subclass of Throwable cannot be generic (§8.1.2)." -
You're not the first person to encounter this problem. This question is very similar. If you dig through the answers and links, it comes down to a bug in the CLR.
EDIT: As a follow up, I've run Martin's example from VS2010 and got the following results:
Sadly, all the SO links to the Microsoft Bug Report are dead now and I haven't been able to find any others.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With