Why can't I catch a generic exception in C#?
Asked Answered
C

3

40

I was doing some unit testing on code that could throw a number of exceptions depending on the inputs. So I tried something like the below code: (simplified for the example)

    static void Main(string[] args)
    {
        RunTest<ArgumentException>();
    }

    static void RunTest<T>() where T : Exception, new()
    {
        try
        {
            throw new T();
            //throw new ArgumentException(); <-- Doesn't work either

        }
        catch (T tex)
        {
            Console.WriteLine("Caught passed in exception type");
        }
        catch (Exception ex)
        {
            Console.WriteLine("Caught general exception");
        }
        Console.Read();
    }

But this will always print out "Caught general exception", the catch(T tex) handler will never work. It doesn't matter whether I throw T() or explicitly throw ArgumentException(). Any ideas why this is? Actually I was kind of surprised that I was even able to use T in the catch clause, but since that's possible shouldn't this work? Or at least give a compiler warning/error that says that this handler will never work?

My environment is Visual Studio 2008 and 3.5 is the target framework.

UPDATE: I tried it now directly from the command prompt and then it prints out "Caught passed in exception type". So it looks like this is restricted to running from within Visual Studio. Maybe a peculiarity of the Visual Studio hosting process?

Cockhorse answered 16/10, 2009 at 12:28 Comment(8)
I just tested it in LinqPad and it printed out Caught passed in exception type. Can you give more details of your environment and framework version.Beryl
That's interesting. I ran it as a console app in VS2008 and it printed Caught general exception.Beryl
Also works in SnippetCompilerCollins
vs2k8 console app and it caught the general exception.Egocentric
It only catches the general one when run from inside VS. Run the exact same program directly from command prompt and it catches the passed in exception type.Cockhorse
Suggest sending this to Eric Lippert for an explanation, sounds like it would make an interesting blog entry.Beryl
Visual studio is interfering with it somehow.Egocentric
It appears that VS2010 (or higher) with .NET 4 behaves as expected. I get "Caught passed in exception type" both under the VS debugger and when run directlyTriny
E
35

Bizarre behavior here...

VS2k8 console app. The following:

try
{
    throw new T();
}
catch (T tex)
{
    Console.WriteLine("Caught passed in exception type");
}
catch (Exception ex)
{
    Console.WriteLine("Caught general exception");
}

results in "Caught general exception".

But, remove the (useless) variables from the catch statements:

try
{
    throw new T();
}
catch (T)
{
    Console.WriteLine("Caught passed in exception type");
}
catch (Exception)
{
    Console.WriteLine("Caught general exception");
}

results in "Caught passed in exception type"!!!


Update:

Heheh... Its a bug: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=362422&wa=wsignin1.0

Source? Here. Why does catch(TException) handling block behaviour differ under the debugger after installing Visual Studio 2008?

Egocentric answered 16/10, 2009 at 12:43 Comment(0)
D
8

It works without Debug

http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/0b0e5bc9-fab2-45b1-863b-40abae370475

Ugly workaround (you may add #if DEBUG) :

  try
  {
    throw new T();
  }
  catch (Exception dbgEx)
  {
    T ex = dbgEx as T;
    if (ex != null)
    {
      Console.WriteLine(ex.Message);
    }
  }
Drawers answered 16/10, 2009 at 12:43 Comment(0)
I
2

It would seem that the most specific type of the exception, when given the choice between T and Exception, is exception, and so that handler is invoked.

I just tried this (you can't do it in C# or VB, but I edited the IL), and changed the second catch clause to catch Object Ex rather than Exception Ex, and in that case, the first handler got hit.

Edit

As others have pointed out, it's more to do with running it in the debugger than the specific type

Insula answered 16/10, 2009 at 12:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.