Question

I am using reflection to analyse a method's exception handling blocks with the [ExceptionHandlingClauses] property of the [MethodBody] class. I could not figure out from MSDN Documentation how this collection behaves and how to interpret it. Let's say you want to assert that:

  • a method contains exactly one try block.
  • that single block contains exactly one catch clause.
  • that single block contains a finally clause.

Please try not to derive context out of the following code as it is too complex to explain here. This is just illustrative code and may be of bad design. Consider the following heirarchy:

// Tier 1. Base class.
namespace ProductName
{
    // This is not an abstract class.
    // These tier 1 class methods to not have implementations or exception handling blocks.
    public class Template: System.IDisposable
    {
        public sealed void Launch () { this.OnLaunch(); }
        public sealed void Simulate () { this.OnSimulate(); }
        public sealed void Test () { this.OnTest(); }
        public sealed void Submit () { this.OnSubmit(); }
        public sealed void Exit () { this.OnExit(); }

        protected virtual void OnLaunch () { }
        protected virtual void OnSimulate () { }
        protected virtual bool OnTest () { return (false); }
        protected virtual void OnSubmit () { }
        protected virtual void OnExit () { }
    }
}

// Tier 2. Defines template platforms e.g. Access, Excel, etc.
// These tier 2 classes do not have implementations or exception handling blocks.
namespace ProductName.Access { public class Template: ProductName.Template { } }
namespace ProductName.Excel { public class Template: ProductName.Template { } }
namespace ProductName.Outlook { public class Template: ProductName.Template { } }
namespace ProductName.PowerPoint { public class Template: ProductName.Template { } }
namespace ProductName.Word { public class Template: ProductName.Template { } }

// Tier 3. Defines individual templates in each platform.
// Each platform will have hundreds of classes with a [Template_########] naming convention.
// Each class overrides all virtual methods with exactly one try/catch/finally block in OnTest and none in other methods.
namespace ProductName.Access.Templates { public class Template_00000001: ProductName.Access.Template { } }
namespace ProductName.Excel.Templates { public class Template_00000001: ProductName.Excel.Template { } }
namespace ProductName.Outlook.Templates { public class Template_00000001: ProductName.Outlook.Template { } }
namespace ProductName.PowerPoint.Templates { public class Template_00000001: ProductName.PowerPoint.Template { } }
namespace ProductName.Word.Templates { public class Template_00000001: ProductName.Word.Template { } }

I already know the following about these classes:

  • Tier 1 base class has no implementation, thus no exception handling blocks.
  • Tier 2 derived classes have no implementation, thus no exception handling blocks.
  • Tier 3 derived classes have implementations of all virtual methods where all methods except [OnTest] do NOT contain exception handling blocks.
  • The [OnTest] method of all Tier 3 classes contains exactly one exception handling block and in some cases a nested block and/or a few [using] statements.

I get all tier 3 classes from this assembly, iterate through each type, get the [MethodInfo] objects for each method, get the [MethodBody] object and inspect its [ExceptionHandlingClauses] collection. The result is quite strange for the [OnTest] method. The [ExceptionHandlingClauses] collection shows up having anywhere between 0 to 6 clauses, each of which has a [Flag] value of either [Catch] or [Finally]. There seems to be absolutely no correlation between the expected number of [catch/finally] blocks and what this collection shows.

Sometimes, it evens shows two [Finally] clauses in methods which do not even have a [try/catch] block.

At first I thought this may have something to with inheritance but none of the base classes have implementations, let alone exception handling blocks.

Some guidance would be appreciated.

Was it helpful?

Solution

The ExceptionHandlingClauses property is providing information about the exception handling clauses in the compiled bytecode. The semantics of exception handling blocks in the bytecode is governed by the ECMA-335 standard, not by ECMA-334 (the C# language standard). The rules for exception handling blocks in C# differ from those imposed by the bytecode, so the compiler sometimes compiles the code in a way that produces what seem to be strange exception handling blocks but in fact result the proper runtime semantics according to the original C# code.

In other cases, C# provides "syntactic sugar" for features not supported by bytecode primitives. For example, the using and lock statements in C# are both implemented by compiling down to try/finally blocks, which will be included in the ExceptionHandlingClauses property.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top