首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TypeSpec元数据表中的流氓条目

TypeSpec元数据表中的流氓条目
EN

Stack Overflow用户
提问于 2011-08-26 10:28:30
回答 2查看 473关注 0票数 5

我有一个.NET库,我试图更多地了解.NET的内部工作原理,所以我正在研究ECMA-335规范,并使用CFF。

我的问题是,在TypeSpec表中,签名是到Blob堆的索引,应该是TypeSpec签名,如第23.2.14节所述。这意味着它可以是一个PTR,FNPTR,数组,SZARRAY,GENERICINSTANCE (为了简洁而删除ELEMENT_TYPE_)。

但是,这个TypeSpec表中有两个条目,它们似乎没有被元数据中的任何其他表引用,它们的类型是VAR0x13和MVAR0x1e。

此程序集是在VS2010中针对.NET 4编译的。

ECMA-335会让我相信这是一个错误,但它是使用MS C#编译器编译的。

有人知道他们是什么以及他们的意思吗?

更新:

经过大量的混乱之后,这段代码在TypeSpec表中创建了这两个条目。

代码语言:javascript
复制
public class AllOutputTypesClass<T> {
    public void GenericMethod<N>(N anItem) {
        string s = anItem.ToString();
    }

    public string GenericMethod<N>(T anItem, N secondItem) {
        return anItem.ToString();
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-08-27 02:46:18

如果您使用ILDasm,您可以得到一个很好的细分的方法,转到视图->元信息->选择更多的十六进制。然后转到视图->元信息->显示!

以下是第二种方法的细目:

代码语言:javascript
复制
    Method #2 (06000002) 
-------------------------------------------------------
    MethodName: GenericMethod (06000002)
    Flags     : [Public] [HideBySig] [ReuseSlot]  (00000086)
    RVA       : 0x0000206c
    ImplFlags : [IL] [Managed]  (00000000)
    CallCnvntn: [DEFAULT]
    hasThis 
    generic 
    Type Arity:1 
    ReturnType: String
    2 Arguments
        Argument #1:  Var!0
        Argument #2:  MVar!!0
    Signature : 30 01 02 0e 13 00 1e 00 
    1 Generic Parameters
        (0) GenericParamToken : (2a000003) Name : N flags: 00000000 Owner: 06000002
    2 Parameters
        (1) ParamToken : (08000002) Name : anItem flags: [none] (00000000)
        (2) ParamToken : (08000003) Name : secondItem flags: [none] (00000000)

如果进一步向下滚动,也会看到TypeSpec表条目。

TypeSpec #1 (1b000001)

代码语言:javascript
复制
TypeSpec : MVar!!0
Signature: 1e 00 

TypeSpec #2 (1b000002)

代码语言:javascript
复制
TypeSpec : Var!0
Signature: 13 00 

上面ILdasm显示的是VAR (1300)是在类级别上传递的泛型!T (类型定义中是泛型param ),而MVAR (1e00)是在方法级别上传递的泛型!n(方法定义中的泛型param )。

但是..。您已经知道了很多,Orion有您的答案- TypeSpec表中的条目正在IL中使用。一个条目在一个方法中使用,另一个在另一个方法中使用。当您查看方法时,您可以在ILdasm中看到这一点:

代码语言:javascript
复制
    .method /*06000001*/ public hidebysig instance void 
        'GenericMethod'<'N'>(!!'N' 'anItem') cil managed
// SIG: 30 01 01 01 1E 00
{
  // Method begins at RVA 0x2050
  // Code size       16 (0x10)
  .maxstack  1
  .locals /*11000001*/ init ([0] string 's')
  IL_0000:  /* 00   |                  */ nop
  IL_0001:  /* 0F   | 01               */ ldarga.s   'anItem'
  IL_0003:  /* FE16 | (1B)000001       */ constrained. !!'N'/*1B000001*/
  IL_0009:  /* 6F   | (0A)000011       */ callvirt   instance string ['mscorlib'/*23000001*/]'System'.'Object'/*01000001*/::'ToString'() /* 0A000011 */
  IL_000e:  /* 0A   |                  */ stloc.0
  IL_000f:  /* 2A   |                  */ ret
} // end of method 'AllOutputTypesClass`1'::'GenericMethod'

代码语言:javascript
复制
.method /*06000002*/ public hidebysig instance string 
        'GenericMethod'<'N'>(!'T' 'anItem',
                             !!'N' 'secondItem') cil managed
// SIG: 30 01 02 0E 13 00 1E 00
{
  // Method begins at RVA 0x206c
  // Code size       19 (0x13)
  .maxstack  1
  .locals /*11000001*/ init ([0] string 'CS$1$0000')
  IL_0000:  /* 00   |                  */ nop
  IL_0001:  /* 0F   | 01               */ ldarga.s   'anItem'
  IL_0003:  /* FE16 | (1B)000002       */ constrained. !'T'/*1B000002*/
  IL_0009:  /* 6F   | (0A)000011       */ callvirt   instance string ['mscorlib'/*23000001*/]'System'.'Object'/*01000001*/::'ToString'() /* 0A000011 */
  IL_000e:  /* 0A   |                  */ stloc.0
  IL_000f:  /* 2B   | 00               */ br.s       IL_0011
  IL_0011:  /* 06   |                  */ ldloc.0
  IL_0012:  /* 2A   |                  */ ret
} // end of method 'AllOutputTypesClass`1'::'GenericMethod'

0x1b表是TypeSpec,因此上面方法中的以下行显示了您想知道的2行的用法:

代码语言:javascript
复制
  IL_0003:  /* FE16 | (1B)000001       */ constrained. !!'N'/*1B000001*/

代码语言:javascript
复制
IL_0003:  /* FE16 | (1B)000002       */ constrained. !'T'/*1B000002*/
票数 2
EN

Stack Overflow用户

发布于 2011-08-26 19:07:49

示例中的两个TypeSpec标记都是从方法实现中的IL引用的,而不是从元数据中引用的。例如,您的方法之一的IL如下所示:

代码语言:javascript
复制
.method public hidebysig instance string 
        GenericMethod<N>(!T anItem,
                         !!N secondItem) cil managed
{
  // Code size       19 (0x13)
  .maxstack  1
  .locals init (string V_0)
  IL_0000:  nop
  IL_0001:  ldarga.s   anItem
  IL_0003:  constrained. !T
  IL_0009:  callvirt   instance string [mscorlib]System.Object::ToString()
  IL_000e:  stloc.0
  IL_000f:  br.s       IL_0011
  IL_0011:  ldloc.0
  IL_0012:  ret
} // end of method AllOutputTypesClass`1::GenericMethod

TypeSpec令牌用于表示受限前缀中的"!T“。您将在另一个方法的正文中看到与其他TypeSpec令牌类似的引用。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7203358

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档