zoukankan      html  css  js  c++  java
  • (翻译)《Expert .NET 2.0 IL Assembler》 第一章 简单示例 1.3 类的预先声明

    返回目录

         这一节只是相关于ILASM的早期版本(1.0和1.1),但是我仍然认为这是有用的信息。考虑一下这些.NET Framework版本的基本大小,你将会不止一次的遇到与这些ILASM的老版本打交道的机会。

         如果你安装了.NET Framework的早期版本,你可以对这个代码示例执行一些试验。在任意文本编辑器中打开这个源文件Simple.il并作出如下修改:将对值类型CharArray8的声明移动到字段Format的前面:

    {


    // End of namespace
    .class public explicit CharArray8
         
    extends [mscorlib]System.ValueType { .size 8  }
    .field public static valuetype CharArray8 Format at FormatData

         事情看起来是井然有序的。但是当你试图编译这个文件时,ILAsm编译器将会失败并报出Unresolved MemberRef ‘Format’的错误信息。

         现在再次修改源文件,这次将对值类型CharArray8的声明移动到命名空间Odd.Or的前面:

    .class public explicit CharArray8
                        
    extends [mscorlib]System.ValueType { .size 8  }
    .namespace Odd.or {
         
    .class public auto ansi Even extends [mscorlib]System.Object {
              
    .field public static int32 val
              
    .method public staticvoid check( ) cil managed {
                   
                   
    ldsflda valuetype CharArray8 Format
                   
              
    // End of method
         
    // End of class
    // End of namespace
    .field public static valuetype CharArray8 Format at FormatData

         现在,当你保存这段源代码并试图重编译它的时候,这就都回复正常了。这里面发生了什么呢?

         在第一次源代码改变后,当Format字段被check方法中的ldsflda指令引用时,值类型CharArray8还没有被声明,它的TypeRef就会因此被忽略,字段引用的签名就会收到该TypeRef作为它的类型。

         接着,值类型CharArray8被声明,一个新的TypeDef被创建。然后,当Format字段确实被声明时,它的类型被当成一个局部声明的值类型,而且该字段的签名定义接收到TypeDef作为它的类型。但是,不存在以TypeRef作为类型的名为Format的字段,被声明在模块中的任何地方。从而,你得到了引用到定义的决定性失败。

         (有一段时间批判ILAsm编译器在编程级别上缺少匹配签名的能力,伴随着类型分析和通过完全名称和决定范围来匹配TypeRef到TypeDef。然而,请耐心一些。)

         第二次改变源代码后,值类型CharArray8首次被声明——以便于所有的引用指向它,而不管这些引用在哪里出现,我们称这个类型为TypeDef。这是一个相当明显的解决方案。

         这个解决方案也会变得不明显——在你考虑两个类的时候,它们的成员互相使用对方的类型作为成员。那么先声明哪一个呢?准确地说,全部。

         在“类定义”章节我提到了类的修正技术,基于ILAsm,允许你重新打开类的范围从而声明更多类的特性和成员。解决这个声明/引用问题的基本方案是,首先为所有的类指定一个空范围类的定义。据此,你可以完全指定所有的类,包括它们的特性和成员,作为修正。“首轮”类的声明应该携带所有类标记、extends子句和implements子句,还应包括所有内嵌类(还有空范围)。你应该将所有这些成员声明维持到后期。

         这种类的预先声明的技术防止了声明/引用错误,而副作用是降低了元数据的大小,因为为了局部化定义的类而忽略多余的TypeRef是不必要的。

        (上述对ILAsm的评论,相应的解答是,编译器确实以最可能快的速度进行签名,而不需要更多高级并缓慢的方法,只要你使用到类的预先声明。)

         类的预先声明的需求,在ILAsm 2.0版本编译器中被消除了。

  • 相关阅读:
    UML用例图
    Google Map API 文档
    chrome 使用各种搜索引擎的方法 GIS
    javaScript 获得触发事件的元素 支持IE FireFox GIS
    html 的路径 GIS
    JavaScript prototype GIS
    chromium 的资源管理 的grit GIS
    [原]使用ucenter最土团购整合DX2bbs的心得
    [转]sqlserver日期函数
    最土Ajax实现/json
  • 原文地址:https://www.cnblogs.com/Jax/p/1251819.html
Copyright © 2011-2022 走看看