The Inquisitive Coder – Davy Brion's Blog

Trying to walk that thin line between intelligence and ignorance

Exceptional Exception Handling Behavior

Posted by Davy Brion on October 8th, 2008

We ran into a weird issue at work today. Take a look at the following code:

    public class MyException : Exception { }

 

    [TestFixture]

    public class TestFixture

    {

        [Test]

        public void Test()

        {

            var exception = GetThrownException<MyException>(() => { throw new MyException(); });

            Assert.IsNotNull(exception);

        }

 

        private T GetThrownException<T>(Action action)

            where T : Exception

        {

            try

            {

                action();

            }

            catch (T exception)

            {

                return exception;

            }

 

            return null;

        }

    }

If you simply run that test, without debugging, it works (both with Testdriven.NET and Resharper). If you run it with a debugger, it fails with the following message:

ExceptionWeirdness.MyException: Exception of type ‘ExceptionWeirdness.MyException’ was thrown.

Pretty weird huh?

Let’s change the code of the GetThrownException method to this:

        private T GetThrownException<T>(Action action)

            where T : Exception

        {

            try

            {

                action();

            }

            catch (T exception)

            {

                return exception;

            }

            catch (Exception e)

            {

                return (T)e;

            }

 

            return null;

        }

Now the test works all the time, even with the debugger attached.

Weird huh? At first i wondered if it was somehow NUnit related… but then i tried running this program:

    public class MyException : Exception { }

 

    class Program

    {

        static void Main(string[] args)

        {

            var exception = GetThrownException<MyException>(() => { throw new MyException(); });

        }

 

        private static T GetThrownException<T>(Action action)

            where T : Exception

        {

            try

            {

                action();

            }

            catch (T exception)

            {

                return exception;

            }

 

            return null;

        }

    }

Run it without the debugger, and it works. Run it with the debugger and it fails.

This is using .NET 3.5 SP1.

I don’t understand why it behaves like this… it should work all the time right? I am overdue for my weekly brain-fart so i might be missing something really stupid though.

Either way, the first person to explain this behavior gets awarded with the “Davy Brion’s Hero Of The Week” title :)

Oh, and this was in a clean solution… so there’s no duplicate MyException types or anything like that.

20 Responses to “Exceptional Exception Handling Behavior”

  1. JacobM Says:

    You may want to check the “Break on exceptions” settings in the VS debugger — you can certainly set it to break on any exception, even if it’s handled. Not what you want in this case.

  2. Davy Brion Says:

    don’t think that makes a difference… the really weird thing is that when the debugger is not attached, the exception is caught by the catch (T exception) handler. When it is attached, the catch (T exception) handler is just not entered.

    Yet, when you put in the catch (Exception exception) handler, and cast the exception to T, it does work when the debugger is attached.

    it’s as if catching exceptions just behaves differently when a debugger is attached… i tried it on 3 different PC’s before i believed it :)

  3. Exceptional exception handling - KoenV Says:

    [...] colleague Davy beat me to post this problem we had today at work, so I’m gonna be lazy and link to him (and steal his title).Btw yesterday we applied this “solution” to one of our biggest projects and [...]

  4. Reflective Perspective - Chris Alcock » The Morning Brew #197 Says:

    [...] Exceptional Exception Handling Behavior – Davy Brion posts about some strange behaviour with exceptions and generics in and out of the debugger. Davy has posed this as a question, so the answer to the problem may be in the comments by the time you read this. [...]

  5. Fabrice Says:

    Seems strange. It works well with .NET 2.0. I tried with VS 2005, and in both cases (debugging or not), it works as expected.

  6. Davy Brion Says:

    that’s good to know… i’ve only tried it with visual studio 2008 sp1 so it might have been introduced by the service pack somehow

  7. Dew Drop - October 9, 2008 | Alvin Ashcraft's Morning Dew Says:

    [...] Exceptional Exception Handling Behavior (Davy Brion) [...]

  8. Bill Pierce Says:

    I have:
    .Net 3.5 SP1
    VS 2008 9.0.30729.1 SP
    ReSharper 3.1 C# Edition 3.1.584.3

    I copied and pasted your test exactly and do not experience the problem when running the test normally, with a debugger attached and no breakpoints, or by stepping through the test in the debugger. Did not attempt debugging a console app.

    Perhaps try adding the serialization constructor to MyException.

  9. Alex Simkin Says:

    I confirm. When stepping through in the debugger, the exception is caught by:

    “catch (Exception ex)” and not by “catch (T ex)” even though type of ex is ExceptionWeirdness.MyException

  10. Davy Brion Says:

    @Alex

    glad we’re not the only ones seeing this problem :)

    @Bill

    interesting… my setup is the following:
    .NET 3.5 SP1
    Visual Studio 2008 9.0.30729.1 SP
    Resharper 4.1.933.3

    i’ve experienced it on 2 pc’s at work, both with the same configuration (the one listed above + windows vista business), and also on my home pc which has XP SP3

    So i guess the only difference (on first sight) is the resharper version… but does resharper even have an impact on the debugger?

  11. den Ben Says:

    “but does resharper even have an impact on the debugger?”

    I believe it has to be able to mingle with it for at least some part. How else would it be able to show that pretty little tests running progress?

  12. Davy Brion Says:

    nope, resharper runs the tests without the debugger by default, so it doesn’t need it… it can just listen to the proper events from the nunit testrunner classes to get all of that information :)

    it can’t be resharper because i just remembered that i also have the problem when running the tests with the Testdriven.NET (with the debugger enabled)

  13. den Ben Says:

    Hmms… this truly is a challenge. And I was so hoping to be your Hero Of The Week :p

    Fact is: Google isn’t going to be much of a help either. When you search for: “catch (T ” debugger 3.5

    …this article is at the top of the list ;-)

  14. Patrick Says:

    Check the following link for the solution: http://blogs.msdn.com/jmstall/archive/2004/10/02/236942.aspx

    The relevant portion is copied below.

    User checks: The biggest culprit: A program can explicitly call System.Diagnostics.Debugger.IsAttached to ask if a managed debugger is attached and then behave differently. (The win32 API IsDebuggerPresent() similarly checks for if a native debugger is attached.). This is the easiest way to cause the most pain. For example, WinForms will explicitly use a different ‘debuggable’ WndProc if a managed debugger is attached. This debuggable wndproc has an extra try-catch around user callbacks (which the non-debuggable wndproc does not have) to notify users if their callbacks are throwing exceptions. Another favorite seems to be throwing exceptions iff a debugger is attached as way of notifying the user.

  15. Davy Brion Says:

    dunno if that’s actually causing the problem… especially because it can be reproduced with very simple code in both a unit test environment and a console application (and i really can’t imagine some kind of background code in a console application causing different debugger behavior). And the code itself doesn’t make any calls to System.Diagnostics.Debugger at all…

    the thing is… the catch (T exception) is not entered, but the catch (Exception e) is entered. And if you then do a (T)e call, it just works. But since the catch (T exception) is listed before the catch (Exception e), and the exception is indeed of type T, then it should in all cases enter the catch(T exception) clause.

  16. Davy Brion Says:

    I submitted a bug to Microsoft Connect for this:

    https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=374919

  17. Koen Says:

    Did scottgu reply yet?

  18. Davy Brion Says:

    he’s probably too busy preparing his Silverlight presentation ;)

  19. Davy Brion Says:

    I’ve heard from someone at MS that this bug is only present on X86

    too bad they don’t update connect…

  20. Peter Says:

    I recommend that everybody that confirmed in the comments that they could repro, confirm this on the connect site as well.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>