1

I believe I'm following the correct process to implement a custom exception, but the exception arrives in the catch block wrapped in a System.Exception, so the handling for my custom exception doesn't execute.

I create the custom exception class (following examples found online):

using System;
using System.Runtime.Serialization;
namespace La.Di.Da
{
    [Serializable]
    public class MyCustomException : Exception
    {
        public MyCustomException()
            : base()
        {
        }

        public MyCustomException(string message)
            : base(message)
        {
        }

    ...
}

I throw the exception, from a lower point in the stack:

...
if (up == down)
{
    throw new MyCustomException("Things are topsy-turvy.");
}
...

The exception is caught at an intermediate try-catch. I know such catching-logging-throwing is wrong practice but this code is in an existing method that's called a lot in this application, and regression testing the entire application for my small change isn't an option. Anyway, this catch-throw isn't causing the problem: The exception arrives in this catch already as a System.Exception wrapping my custom exception.

try
{
    DoSomeStuff(();
}
catch (Exception ex)
{
    LogManager.Instance.LogException(ex);
    throw;
}
finally
{
    DoSomeCleanup();
}

I have code to catch the custom exception at the next catch up the stack. But the exception arrives as a System.Exception wrapping the custom exception, so my custom exception handling doesn't get executed.

...
try
{
    CallAMethod();
}
catch MyCustomException(ex)
{
    LogManager.Instance.LogException(ex);
    ShowErrorMessage(ex.Message);
}
catch Exception(ex)
{
    throw ex;
}

I believe the exception I'm throwing shouldn't be wrapped, so I must be doing something wrong. Any suggestions?

Bryan H.
  • 26
  • 3
  • I just tried to reproduce your error, but couldn't (ie I was able to catch the re-thrown custom exception as it's original type). You'll have to give us more context... – Miles B. Aug 01 '17 at 18:45
  • I am also not able to recreate your scenario. In my test, the control rightly goes to the `MyCustomException` catch blow. – Subbu Aug 01 '17 at 18:56

3 Answers3

1
public class MyCustomException : Exception

That code means your class is extending the Exception class. So when you throw it, and catch it with an Exception catch, it is held as that base class. You can always cast it back to MyCustomException.

If by wrapping, you mean that your custom exception is included as an inner exception, it's likely because of your re-throwing the exception.

It also may be how your second set of try catches function. I haven't seen that style before so it may be valid, but try it written as

catch(MyCustomException ex){
...
}

instead

Matti Price
  • 3,351
  • 15
  • 28
  • Regarding the style, that's our standard. We have StyleCop enforcing it. – Bryan H. Aug 01 '17 at 19:33
  • If you want to re-throw an exception, just use `throw` instead of `throw ex`, otherwise you will mess up your stack trace. See https://stackoverflow.com/questions/178456/what-is-the-proper-way-to-re-throw-an-exception-in-c – Bradley Uffner Aug 01 '17 at 19:34
1

Why?

An exception handler will catch any exception that is or is derived from the specified exception type.

For example

catch (System.Exception e)
{
    //Handler
}

...will catch everything. Meanwhile

catch (System.ApplicationException e)
{
    //Handler
}

...will catch all exceptions that derive from ApplicationException. This includes all of these:

Microsoft.JScript.NoContextException, Microsoft.JScript.ReturnOutOfFinally, System.Reflection.InvalidFilterCriteriaException, System.Reflection.TargetException, System.Reflection.TargetInvocationException, System.Reflection.TargetParameterCountException, System.Threading.WaitHandleCannotBeOpenedException

This is exactly why you should never catch System.Exception. It catches everything!

This is also why exception handlers are declared in order from specific to general-- if the general handler were first, none of the other handlers would ever fire.

How to fix

Get rid of the catch (System.Exception) if you can.

Workaround

If you can't get rid of your catch (System.Exception) block, you can use a when filter so that it will ignore your custom exception, like this:

catch (System.Exception e) when (!(e is MyCustomException))
{
    //Handler
}
John Wu
  • 50,556
  • 8
  • 44
  • 80
0

Not an answer to your query, but generally, your Custom exception should include these 3 constructors (may be you already have it)

Exception best practices

Use at least the three common constructors when creating your own exception classes: the default constructor, a constructor that takes a string message, and a constructor that takes a string message and an inner exception.

This will allow you to chain exceptions, i.e., the InnerException property can contain another exception object, whose InnerException can contain another one, and so on.

Also, your handler which has just the throw statement is the correct way (in most cases), as it would preserve the stack trace info.

Subbu
  • 2,130
  • 1
  • 19
  • 28