stakx stakx - 4 years ago 92
C# Question

How are CIL 'fault' clauses different from 'catch' clauses in C#?

According to the CLI standard (Partition IIA, chapter 19) and the MSDN reference page for the

enum, there are four different kinds of exception handler blocks:


  • catch clauses: "Catch all objects of the specified type."

  • filter clauses: "Enter handler only if filter succeeds."

  • finally clauses: "Handle all exceptions and normal exit."

  • fault clauses: "Handle all exceptions but not normal exit."



Given these brief explanations (cited from the CLI Standard, btw.), these should map to C# as follows:


  • catch
    catch (FooException) { … }

  • filter — not available in C# (but in VB.NET as
    Catch FooException When booleanExpression
    )

  • finally
    finally { … }

  • fault
    catch { … }



Experiment:



A simple experiment shows that this mapping is not what .NET's C# compiler really does:

// using System.Linq;
// using System.Reflection;

static bool IsCatchWithoutTypeSpecificationEmittedAsFaultClause()
{
try
{
return MethodBase
.GetCurrentMethod()
.GetMethodBody()
.ExceptionHandlingClauses
.Any(clause => clause.Flags == ExceptionHandlingClauseOptions.Fault);
}
catch // <-- this is what the above code is inspecting
{
throw;
}
}


This method returns
false
. That is,
catch { … }
has not been emitted as a fault clause.

A similar experiment shows that in fact, a catch clause was emitted (
clause.Flags == ExceptionHandlingClauseOptions.Clause
), even though no exception type has been specified.

Questions:




  1. If
    catch { … }
    really is a catch clause, then how are fault clauses different from catch clauses?

  2. Does the C# compiler ever output fault clauses at all?


Answer Source

there are four different kinds of exception handler blocks:

  • catch clauses: "Catch all objects of the specified type."
  • filter clauses: "Enter handler only if filter succeeds."
  • finally clauses: "Handle all exceptions and normal exit."
  • fault clauses: "Handle all exceptions but not normal exit."

Given these brief explanations (cited from the CLI Standard, btw.), these should map to C# as follows:

  • catchcatch (FooException) { … }
  • filter — not available in C# (but in VB.NET as Catch FooException When booleanExpression)
  • finallyfinally { … }
  • faultcatch { … }

It's that last line where you went wrong. Read the descriptions again. fault and finally are described practically identically. The difference between them is that finally is always entered, whereas fault is only entered if control leaves the try via an exception. Note that this means that a catch block may have already acted.

If you write this in C#:

try {
    ...
} catch (SpecificException ex) {
    ...
} catch {
    ...
}

Then there is no way that the third block will be entered if control leaves the try via a SpecificException. That's why catch {} isn't a mapping for fault.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download