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!!!");
}
}
}
}
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:
Targetting .NET 4, PASS
Targetting .NET 3.5, FAIL
Targetting .NET 3.5 in RELEASE mode, PASS
Sadly, all the SO links to the Microsoft Bug Report are dead now and I haven't been able to find any others.
(This is not a concrete answer; but I could not post it as a comment too.)
I can not reproduce this (VS 2012, .NET 4.5, C# 5.0, every SP installed).
I defined this exception class:
class MyException : Exception
{
public MyException() { }
public MyException(string message) : base(message) { }
}
and a method:
static void Throws<T>(Action action) where T : Exception
{
try
{
action();
}
catch (T) { Console.WriteLine("got {0}", typeof(T)); }
catch (Exception) { Console.WriteLine("got Exception"); }
}
and I have tested it this way:
Throws<MyException>(() => { throw new MyException(); });
int result = 0;
Throws<DivideByZeroException>(() => result = result / result);
and the output is:
got Draft.MyException
got System.DivideByZeroException
So (IMHO) you should look somewhere else.
Related
I have a general retry on exception handler which I would like it to repeat a function for a definite number of time and here's the code for it
public static void Retry(this MethodInfo methodInfo, object[] parametrsList, short after = 0, short? retry = 1)
{
if (retry < 0)
return;
try
{
short waitingPeriodMs = after*1000;
Thread.Sleep(waitingPeriodMs);
Type classObjType = methodInfo.ReflectedType;
object classObj = Activator.CreateInstance(classObjType);
methodInfo.Invoke(classObj, parametrsList);
}
catch (TargetInvocationException ex)
{
Debug.WriteLine("Exception Caught");
methodInfo.Retry(parametrsList, after, --retry);
}
catch (Exception ex)
{
Debug.WriteLine("Exception Caught");
methodInfo.Retry(parametrsList, after, --retry);
}
}
The problem is whenever I an unhandled exception is throw in the method that I'm invoking neither of the two catch statements catches it
I've made sure that the Use Only My Code checkbox is not checked
I've used those two Debug.Writeline statements to make sure that it's not a debugger related issue and checked the Output window and made sure those two statements were not executed
P.S. I'm aware the using a general retry on exception code is risky and could lead to an infinite number of retries the I'm using it because of a project related reason
Update:
A unit test example that reproduces the question
[TestClass]
public class ExceptionTest
{
[TestMethod]
public void TestExceptionRetry()
{
Action act = () => { throw new Exception(); };
act.Method.Retry(new object[0]);
}
}
This is a new attempt to pose a version of a question asked less successfully this morning.
Consider the following program, which we'll run once inside Visual Studio 2010 and once more by double-clicking the executable directly
namespace ConsoleApplication3
{
delegate void myFoo(int i, string s);
class Program
{
static void Main(string[] args)
{
Foo(1, "hello");
Delegate Food = (myFoo)Foo;
Food.DynamicInvoke(new object[] { 2, null });
}
static void Foo(int i, string s)
{
Console.WriteLine("If the next line triggers an exception, the stack will be unwound up to the .Invoke");
Console.WriteLine("i=" + i + ", s.Length = " + s.Length);
}
}
}
When the exception in Foo triggers while running VS, the debugger shows the stack correctly and shows that the problem occured on the second WriteLine in Foo.
But when the exception occurs while running the executable directly, one gets a little popup window from the CLR indicating that the program threw an unhandled exception. Click debug and select the VS debugger. In this case, the stack unwinds up to the point of the most recent .DynamicInvoke and when you attach with the debugger, the stack context that existed at the time of the exception has been partially lost.
It does exist, in a limited form, within the "inner exception" portion of the exception event. You click to expand the associated information and find the line number where the problem occured. But obviously local variables and other context will be gone.
If one tries the same thing but without the .DynamicInvoke (for example, call Foo(1, null) on line 1 of Main), still by double-clicking the .exe file, we DO get the correct line number when the debugger attaches. Similarly if the application is launched by clicking on the .exe, but then the debugger is attached before the exception gets thrown.
Does anyone know how an application using dynamic reflection/invocation could avoid this problem? In my intended use case, in a system the name of which I won't mention here, I cannot predict the type signature of the object that will be used in the .DynamicInvoke, or even the number of arguments that will be employed, hence static typing or even generics aren't a way out of this.
My question is this: does anyone know why we get such different behaviors when running directly from the debugger versus when attaching to the program after the exception is thrown?
As per the comments, whether you see the NullReferenceException as unhandled depends on whether it's handled. Here are some ways to call Foo, the first three will leave the exception as unhandled, the last two will handle the NullReferenceException by wrapping it, and throwing a new exception.
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace ConsoleApplication3
{
delegate void myFoo(int i, string s);
internal class Program
{
private static void Main(string[] args)
{
Foo(1, "hello");
// From a delegate
try
{
Delegate Food = (myFoo)Foo;
((dynamic)Food).Invoke(2, null);
}
catch (NullReferenceException ex)
{ Console.WriteLine("Caught NullReferenceException at " + ex.StackTrace); }
MethodInfo Foom = typeof(Program).GetMethod("Foo", BindingFlags.Static | BindingFlags.NonPublic);
// From a MethodInfo, obtaining a delegate from it
try
{
Delegate Food = Delegate.CreateDelegate(typeof(Action<,>).MakeGenericType(Foom.GetParameters().Select(p => p.ParameterType).ToArray()), Foom);
((dynamic)Food).Invoke(2, null);
}
catch (NullReferenceException ex)
{ Console.WriteLine("Caught NullReferenceException at " + ex.StackTrace); }
// From a MethodInfo, creating a plain Action
try
{
Expression.Lambda<Action>(
Expression.Call(
Foom,
Expression.Constant(2),
Expression.Constant(null, typeof(string)))).Compile()();
}
catch (NullReferenceException ex)
{ Console.WriteLine("Caught NullReferenceException at " + ex.StackTrace); }
// MethodBase.Invoke, exception gets wrapped
try
{
Foom.Invoke(null, new object[] { 2, null });
}
catch (NullReferenceException)
{ Console.WriteLine("Won't catch NullReferenceException"); }
catch (TargetInvocationException)
{ Console.WriteLine("Bad!"); }
// DynamicInvoke, exception gets wrapped
try
{
Delegate Food = (myFoo)Foo;
Food.DynamicInvoke(2, null);
}
catch (NullReferenceException)
{ Console.WriteLine("Won't catch NullReferenceException"); }
catch (TargetInvocationException)
{ Console.WriteLine("Bad!"); }
}
private static void Foo(int i, string s)
{
Console.WriteLine("i=" + i + ", s.Length = " + s.Length);
}
}
}
Actually answered by #hvd:
((dynamic)Food).Invoke(2, null);
solves my problem in one line of code. Thanks!
How is it possible to resume code execution after an exception is thrown?
For example, take the following code:
namespace ConsoleApplication1
{
public class Test
{
public void s()
{
throw new NotSupportedException();
string #class = "" ;
Console.WriteLine(#class);
Console.ReadLine();
}
}
public class Program
{
public static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
}
catch (Exception ex)
{
}
}
}
}
After catching the exception when stepping through, the program will stop running. How can I still carry on execution?
EDIT: What I specifically mean is the line Console.WriteLine(#class); does not seem to be hit, because when I run to it when in debug mode, the program exits from debug mode. I want to run to this line and stop at it.
Thanks
Well, you don't have any code after the catch blocks, so the program would stop running. Not sure what you're trying to do.
The following should be proof that the program doesn't simply "stop" after the catch blocks. It will execute code after the catch blocks if there is code to be executed:
static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
Console.WriteLine("ArgumentException caught!");
}
catch (Exception ex)
{
Console.WriteLine("Exception caught!");
}
Console.WriteLine("I am some code that's running after the exception!");
}
The code will print the appropriate string depending on the exception that was caught. Then, it will print I am some code that's running after the exception! at the end.
UPDATE
In your edit you asked why Console.WriteLine(#class); does not seem to be hit. The reason is that you are explicitly throwing an exception in the very first line of your s() method; anything that follows is ignored. When an exception is encountered, execution stops and the exception is propagated up the call stack until the appropriate handler can handle it (this may be a catch block that corresponds to the try that wraps the statement in question within the same method, or it may be a catch block further up the call-stack. If no appropriate handler is found, the program will terminate with a stacktrace [at least in Java - not sure if the same happens in C#]).
If you want to hit the Console.WriteLine line, then you shouldn't be explicitly throwing an exception at the beginning of the method.
It sounds like you're wanting resumeable exceptions. C# doesn't do resumeable exceptions, and I'm doubtful that CLR supports them.
The purpose of throwing an exception is to abort a function and an entire operation (call stack) if/when something in the call environment (parameters, object state, global state) makes the function's operation impossible or invalid. Passing a zero param to a function that needs to divide a quantity by that param, for example. Division by zero won't produce a meaningful result, and if that's the sole purpose of the function, then the function can't return a meaningful result either. So, throw an exception. This will cause execution to jump to the nearest catch or finally block on the call stack. There is no returning to the function that threw the exception.
If you want to step into your code in the debugger to trace the Console.WriteLine() calls, you need to remove the throw new NotSupportedException() line from your code and recompile.
If you're worried that an exception will be thrown in the method but you want the method to continue, add an error handler inside the method.
class Test
{
public void s()
{
try
{
// Code that may throw an exception
throw new NotSupportedException();
}
catch(Exception ex)
{
// Handle the exception - log?, reset some values?
}
string #class = "" ;
Console.WriteLine(#class);
Console.ReadLine();
}
}
You could also return a bool or some other value to indicate the state.
Disclaimer: I am not suggesting that you actually do this.
You can mimic the old VB style On Error Resume Next with the following code.
public static class ControlFlow
{
public static Exception ResumeOnError(Action action)
{
try
{
action();
return null;
}
catch (Exception caught)
{
return caught;
}
}
}
And then it could be used like the following.
public static void Main()
{
ControlFlow.ResumeOnError(() => { throw new NotSupportedException(); });
ControlFlow.ResumeOnError(() => { Console.WriteLine(); });
ControlFlow.ResumeOnError(() => { Console.ReadLine(); });
}
Some simple code I put together to catch exceptions that are thrown inside a catch block:
try
{
//do code here
}
catch (Exception ex)
{
try { SomeMethod1(); }
catch { }
try { SomeMethod2(); }
catch { }
try { SomeMethod3(); }
catch { }
}
finally
{
//cleanup goes here
}
Execution is still carying on but there is no code after the exception is caught. If you want to repeatedly call s then consider wrapping the try/catch block in a while loop.
The program stops running because there is no following code to be executed in the Main() method! You can add the following line to your code to keep the program running until there is a console input:
Console.ReadLine();
For that code, you can't. If you break the tasks up to smaller chunks, you can resume at the next chunk. But normally it's easier to have a different mechanism than exceptions to report non-fatal errors, such as a callback function which returns whether or not to continue.
You can use the "step-over" feature in debugging to achieve this on a per-run basis.
Instead of thowing the NotSupportedException, you could track that an exception was encountered, use a default value, and throw the exception at the end of the method call:
namespace ConsoleApplication1
{
public class Test
{
public void s()
{
bool exceptionEncountered = false;
if(someConditionNotSupported){//stub condition
exceptionEncountered=true
#class="DefaultValue";
}
Console.WriteLine(#class);
Console.ReadLine();
if(exceptionEncountered){
throw new NotSupportedException();
}
}
}
public class Program
{
public static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
}
catch (Exception ex)
{
}
}
}
}
public static void Main()
{
for (int j = 0; j <= 100000; j++)
{
try
{
// TODO: Application logic...
}
catch
{
System.Threading.Thread.Sleep(1000);
}
}
}
In the following method, the first catch block is never run, even when an exception of type ExceptionType is thrown:
/// <summary>
/// asserts that running the command given throws an exception.
/// </summary>
public static void Throws<ExceptionType>(ICommand cmd)
where ExceptionType : Exception
{
// Strangely, using 2 catch blocks on the code below makes the first catch block do nothing.
try
{
try
{
cmd.Execute();
}
catch (ExceptionType)
{
return;
}
}
catch (Exception f)
{
throw new AssertionException(cmd.ToString() + " threw an exception of type " + f.GetType() + ". Expected type was " + typeof(ExceptionType).Name + ".");
}
throw new AssertionException(cmd.ToString() + " failed to throw a " + typeof(ExceptionType).Name + ".");
}
as indicated by the following test:
[Test]
public void Test_Throws_CatchesSpecifiedException()
{
AssertThat.Throws<AssertionException>(
new FailureCommand()
);
}
using the following class:
class FailureCommand : ICommand
{
public object Execute()
{
Assert.Fail();
return null; // never reached.
}
public override string ToString()
{
return "FailureCommand";
}
}
giving the following output in NUnit:
TestUtil.Tests.AssertThatTests.Test_Throws_CatchesSpecifiedException:
FailureCommand threw an exception of type NUnit.Framework.AssertionException. Expected type was AssertionException.
I also tried using 2 catch blocks for 1 try block (instead of nesting a try/catch within an outer try), but got the same results.
Any ideas as to how to catch the exception specified as a type parameter in one catch block, but catch all other exceptions in the other?
Works fine for me in this test:
using System;
using System.IO;
class Test
{
static void Main()
{
Throws<ArgumentNullException>(() => File.OpenText(null));
}
public static void Throws<ExceptionType>(Action cmd)
where ExceptionType : Exception
{
try
{
try
{
cmd();
}
catch (ExceptionType)
{
Console.WriteLine("Caught!");
return;
}
}
catch (Exception f)
{
Console.WriteLine("Threw an exception of type " + f.GetType()
+ ". Expected type was " + typeof(ExceptionType) + ".");
}
Console.WriteLine("No exception thrown");
}
}
How certain are you that the two AssertionException exceptions are identical? Are they definitely in the same namespace (print typeof(ExceptionType) rather than just the Name property)? Are they from the same assembly? I wouldn't be surprised to find some oddities due to multiple test framework versions coexisting...
Try it with an exception other than AssertionException to make life simpler.
See this thread for more info:
Why can't I catch a generic exception in C#?
Seems to be a bug:
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=362422&wa=wsignin1.0
I haven't debugged this code or looked at it too long but could it be that you first "return" statement is causing the code to HALT and leave the method. Therefore, the exception is "caught" or "handled" (however you look at it) and the outer try/catch block is never executed.
Are you trying to do this?
try
{
try
{
cmd.Execute();
}
catch (ExceptionType)
{
throw;
}
}
catch (Exception f)
{
throw new AssertionException(cmd.ToString() + " threw an exception of type " + f.GetType() + ". Expected type was " + typeof(ExceptionType).Name + ".");
}
In the class:
private Func<T, object> pony;
In my function:
object newValue;
try {
newValue = pony.Invoke(model as T); // This is the line where I get an exception!
} catch (Exception exception) {
// This code is never run, even though I get an exception two lines up!
if(exception is DivideByZeroException) throw new DivideByZeroException("Division by zero when calculating member " + GetMemberName(), exception);
throw;
}
I expect to get exceptions when I throw them, but I get a DivideByZeroException on the line newValue = pony.Invoke(model as T);. Why is this? Can I do something about it?
This is in a asp.net mvc2-application running in Cassini at the moment.
If I select Start debugging in Visual Studio 2008, the error gets caught and rethrown with the extra information!
The problem was that I obviously haven't understood how inner exceptions work. The exception gets caught but then only the inner exception is shown, and that's a totally other issue.
Exceptions thrown from a compiled expression are handled normally by the try .. catch construct, so I'd expect that there is some other issue in your code. If you try for example the following code, it behaves as expected:
Expression<Func<int, int>> f = x => 10 / x;
Func<int, int> fcompiled = f.Compile();
try {
Console.WriteLine(fcompiled(0));
} catch (DivideByZeroException e) {
Console.WriteLine("Divison by zero");
}
As a side note, you should probably handle DivideByZeroException using a separate catch (as I did in my example). This is a cleaner and recommended way to catch different types of exceptions.
Can you check whether the exception is really unhandled when running the application without debugging (for example by adding some debug print to the catch block)? What exception is printed when you run the application (afterall, your code rethrows some exception in any case, so the output may not be clear).
The following code worked for me (this is in a C# console app, although I don't know why that would work differently from ASP.NET):
class Program
{
static void Main(string[] args)
{
var foo = new Foo<int>();
try
{
Console.WriteLine("Calling function");
foo.DoStuff(5);
}
catch(Exception ex)
{
Console.WriteLine("Caught exception: " + ex.ToString());
}
finally
{
Console.WriteLine("In finally block");
}
}
}
class Foo<T>
{
private Func<T, object> pony;
public Foo()
{
this.pony = m =>
{
throw new DivideByZeroException("Exception!");
};
}
public object DoStuff(T o)
{
return this.pony.Invoke(o);
}
}
This prints out the contents of the exception to the command line, as expected.
Well, the code executed in the compiled expression obviously generates the DivideByZeroException, right. Something tries to divide by zero in that. So what else would you expect?
Note that the debugger (especially VS) may break on exceptions, so that you should make sure to continue running the application, it should reach your catch block just fine.