1

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.

4

1 回答 1

3

ExceptionHandlingClauses属性提供有关已编译字节码中异常处理子句的信息。字节码中异常处理块的语义由 ECMA-335 标准而非 ECMA-334(C# 语言标准)管理。C# 中异常处理块的规则与字节码强加的规则不同,因此编译器有时编译代码的方式会产生看似奇怪的异常处理块,但实际上会根据原始 C# 代码产生正确的运行时语义.

在其他情况下,C# 为字节码原语不支持的功能提供“语法糖”。例如 C# 中的usingandlock语句都是通过编译成try/finally块来实现的,它会包含在ExceptionHandlingClauses属性中。

于 2013-05-13T22:26:18.787 回答