解释MethodBody.ExceptionHandlingClauses集合

时间:2013-05-13 21:29:20

标签: c# .net reflection methodinfo

我使用反射来分析具有[ExceptionHandlingClauses]类的[MethodBody]属性的方法的异常处理块。我无法从MSDN Documentation中弄清楚这个集合的行为以及如何解释它。假设你想断言:

  • 一个方法只包含一个try块。
  • 该单个块只包含一个catch子句。
  • 该单个块包含finally子句。

请尽量不要从以下代码中导出上下文,因为它太复杂,无法在此解释。这只是说明性代码,可能设计不佳。考虑以下的层次结构:

// 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 { } }

我已经知道以下关于这些类的内容:

  • 第1层基类没有实现,因此没有异常处理块。
  • 第2层派生类没有实现,因此没有异常处理块。
  • 第3层派生类具有所有虚方法的实现,其中除[OnTest]之外的所有方法都不包含异常处理块。
  • 所有第3层类的[OnTest]方法只包含一个异常处理块,在某些情况下还包含嵌套块和/或一些[using]语句。

我从这个程序集中获取所有第3层类,遍历每个类型,获取每个方法的[MethodInfo]个对象,获取[MethodBody]对象并检查其[ExceptionHandlingClauses]集合。 [OnTest]方法的结果非常奇怪。 [ExceptionHandlingClauses]集合显示在0到6个子句之间,每个子句的[Flag]值为[Catch][Finally]。预期的[catch/finally]块数与此集合显示的内容之间似乎完全没有关联。

有时,它甚至会在方法中显示两个[Finally]子句,这些子句甚至没有[try/catch]块。

起初我认为这可能与继承有关,但没有基类具有实现,更不用说异常处理块了。

一些指导意见将不胜感激。

1 个答案:

答案 0 :(得分:3)

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

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