Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens if the filter of an Exception filter throws an exception

Tags:

c#

c#-6.0

I have not worked in C# 6 yet but was wondering....

As the title says "What happens if the filter of an Exception filter throws an exception?". I guess the really answer is "The filter should be written in such a way that it never throws an exception.", but lets say it does. Will it be as if the exception happened inside the catch itself?

try
{
  throw new Exception("Forced Exception");
}
catch (Exception ex) when (MethodThatThrowsAnException())
{
  WriteLine("Filtered handler 1");
}
catch (Exception ex)
{
  WriteLine("Filtered handler 2");
}

Or

try
{
  throw new Exception("Forced Exception");
}
catch (Exception ex) when (MethodThatThrowsAnException())
{
  WriteLine("Filtered handler 1");
}

Edit: Interesting Example This section was removed because of a bug in alleged volatileread upon which the example was based. Further investigation is required

like image 453
Murdock Avatar asked Mar 05 '15 13:03

Murdock


People also ask

What is the meaning of filter threw exception?

If there is an exception thrown within the filter, then that exception will be silently swallowed and the filter simply fails. This causes the original exception to go down the catch cases or ultimately end up being reraised upwards.

When should you use an exception filter?

Exception filters are preferable to catching and rethrowing because they leave the stack unharmed. If the exception later causes the stack to be dumped, you can see where it originally came from, rather than just the last place it was rethrown.

What happens when an exception is thrown in a try block?

Answer: When an exception is thrown in the catch block, then the program will stop the execution. In case the program has to continue, then there has to be a separate try-catch block to handle the exception raised in the catch block.


3 Answers

If there is an exception thrown within the filter, then that exception will be silently swallowed and the filter simply fails. This causes the original exception to go down the catch cases or ultimately end up being reraised upwards.

So the code calling the filter will not have a way to know that there was actually an exception within your filter method. Thus, it’s important to avoid conditions where an exception can be thrown to make sure that a filter doesn’t fail for this reason.

You can verify this using the following code on volatileread.com’s C# 6 beta interpreter:

public void Main ()
{
    try
    {
        try
        {
            throw new Exception("Original exception");
        }
        catch (Exception ex)
            when (Test()) // `if (Test())` in older previews
        {
            Console.WriteLine("Caught the exception");
        }
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
    }
}

public static bool Test ()
{
    throw new Exception("Exception in filter condition");
}

This results in the “Original exception” appearing in the outer try/catch block.


Update

Since I didn’t understand the output from volatileread’s compiler when not using the outer try/catch block, I installed the MS Build Tools 2015 myself (which as of the time of this answer still uses if, not when) and tried it out. It turns out that when not using the outer try/catch, the “original exception” is still the one that causes the program to crash. So it’s not the filter exception. This seems to be a bug with volatile’s compiler.

like image 175
poke Avatar answered Oct 16 '22 18:10

poke


You can try it out here.

As @Habib correctly indicates, the filter simply gets skipped and it's as if it never existed. From that point on, the catch clauses work as they always have. The example above demonstrates this.

However if you change the second catch clause to a type that cannot catch whatever is thrown from your method, your program will crash because of an unhandled exception.

Spicy detail (bug): if you call the method encompassing the try-catch via reflection and a when clause throws an exception then it will be this exception that is considered unhandled and not the original one. More information here.

like image 22
Jeroen Vannevel Avatar answered Oct 16 '22 19:10

Jeroen Vannevel


Edit: The oddness seems to be caused by a bug in volatileread. Please refer to poke's answer. The experiments below can not be trusted

So I ran a few experiments that gave a few interesting results to shed some light on the issue.

Check using http://volatileread.com/utilitylibrary/snippetcompiler?id=7632

public void Main()
{
  try
  {
    throw new Exception("Forced Exception");
  }
  catch (Exception ex) when (MethodThatThrowsAnException())
  {
    Console.WriteLine("Filtered handler 1");
  }
  catch (Exception ex)
  {
    Console.WriteLine("Filtered handler 2");
  }
}

private bool MethodThatThrowsAnException()
{
  throw new Exception();   
}

Prints out "Filtered handler 2"

public void Main()
{
  try
  {
    throw new Exception("Forced Exception");
  }
  catch (Exception ex) when (MethodThatThrowsAnException())
  {
    Console.WriteLine("Filtered handler 1");
  }

}

private bool MethodThatThrowsAnException()
{
  throw new Exception("MethodThatThrowsAnException");   
}

Prints out:

Unhandled Expecption: System.Exception: MethodThatThrowsAnException
at Program.MethodThatThrowsAnException() at Program.Main()

Another interesting output for

   public void Main()
    {
      try
      {
        throw new Exception("Forced Exception");
      }
      catch (Exception ex) when(MethodThatThrowsAnException())
      {
        Console.WriteLine("Filtered handler 1");
      }
      catch (Exception ex) when(MethodThatThrowsAnException2())
      {
        Console.WriteLine("Filtered handler 2");

      }
    }

    private bool MethodThatThrowsAnException()
    {
      throw new Exception("MethodThatThrowsAnException");   
    }

    private bool MethodThatThrowsAnException2()
    {
      throw new Exception("MethodThatThrowsAnException2");   
    }

Unhandled Expecption: System.Exception: MethodThatThrowsAnException2 at Program.MethodThatThrowsAnException2() at Program.Main()

So it seems like it tries to evaluated the first catch if it throws an exception it continues to the next catch. The first catch that does not fail and matches all conditions then handles the exception (BTW an exception of the type originally thrown in the try). However if the last catch that is of the type of the thrown error also throws an exception in the filter part then an Unhandled Exception is thrown of the type in the filter.

Edit: Note:

public void Main()
{
  try
  {
    try
    {
      throw new Exception("Forced Exception");
    }
    catch (Exception ex) when (MethodThatThrowsAnException())
    {
      Console.WriteLine("Filtered handler 1");
    }
  }
  catch (Exception ex)
  {
      Console.WriteLine("Caught");
      Console.WriteLine(ex);
  }
}

private bool MethodThatThrowsAnException()
{
  throw new Exception("MethodThatThrowsAnException");   
}

Outputs:

Caught

System.Exception: Forced Exception at Program.Main()

If you compare that with the second output... HOW THE HELL IS THAT POSSIBLE??? In the second example MethodThatThrowsAnException is thrown but in the last example "Forced Exception" is caught

like image 26
Murdock Avatar answered Oct 16 '22 20:10

Murdock