关于 C# 编译器如何发出 TypeRef 信息的问题
当我尝试 C# 4.0 中的新功能“可选参数”时,我发现了这个有趣的事情。
我知道在 C# 4.0 中有两种使用“可选参数”的方法:
static void TestMethod(int parameter = 5) { }
static void TestMethod2([Optional, DefaultParameterValue(5)]int parameter) { }
现在,如果我编译此代码,然后使用 IL Dasm 查看程序集,那么我会在 IL Dasm 的“MetaInfo”窗口中看到,有对OptionalAttribute 的类型引用如下所示:
Token: 0x01000002
ResolutionScope: 0x23000001
TypeRefName: System.Runtime.InteropServices.OptionalAttribute
MemberRef #1 (0a000001)
-------------------------------------------------------
Member: (0a000001) .ctor:
CallCnvntn: [DEFAULT]
hasThis
ReturnType: Void
No arguments.
但没有DefaultParameterValueAttribute 的迹象。 这是为什么?
实际上我认为这两个属性都不应该在这里,因为编译器对它们的处理方式不同,它们有自己的标志值。为了解释我的意思,请看一下这个:
Method #2 (06000002)
-------------------------------------------------------
MethodName: TestMethod (06000002)
Flags : [Private] [Static] [HideBySig] [ReuseSlot] (00000091)
RVA : 0x00002053
ImplFlags : [IL] [Managed] (00000000)
CallCnvntn: [DEFAULT]
ReturnType: Void
1 Arguments
Argument #1: I4
1 Parameters
(1) ParamToken : (08000002) Name : parameter flags: [Optional] [HasDefault] (00001010) Default: (I4) 5
Method #3 (06000003)
-------------------------------------------------------
MethodName: TestMethod2 (06000003)
Flags : [Private] [Static] [HideBySig] [ReuseSlot] (00000091)
RVA : 0x00002056
ImplFlags : [IL] [Managed] (00000000)
CallCnvntn: [DEFAULT]
ReturnType: Void
1 Arguments
Argument #1: I4
1 Parameters
(1) ParamToken : (08000003) Name : parameter flags: [Optional] [HasDefault] (00001010) Default: (I4) 5
那就是两个方法的元数据。我们可以看到每个代码段的最后一行已经存储了默认的参数值,那么为什么还要引用OptionalAttribute呢?
I found this interesting thing when I was trying out the new feature “optional parameters” in C# 4.0.
I know that there are two ways to use “optional parameters” in C# 4.0:
static void TestMethod(int parameter = 5) { }
static void TestMethod2([Optional, DefaultParameterValue(5)]int parameter) { }
Now if I compile this code and then view the assembly using IL Dasm, then I’ll see that in the “MetaInfo” window of IL Dasm, there is a type reference to OptionalAttribute like this:
Token: 0x01000002
ResolutionScope: 0x23000001
TypeRefName: System.Runtime.InteropServices.OptionalAttribute
MemberRef #1 (0a000001)
-------------------------------------------------------
Member: (0a000001) .ctor:
CallCnvntn: [DEFAULT]
hasThis
ReturnType: Void
No arguments.
But there is no sign of DefaultParameterValueAttribute.
Why is that?
Actually I think the two attributes both should not be here, because they are treated differently by the compiler, they have their own flag values. To explain what I mean, please take a look at this:
Method #2 (06000002)
-------------------------------------------------------
MethodName: TestMethod (06000002)
Flags : [Private] [Static] [HideBySig] [ReuseSlot] (00000091)
RVA : 0x00002053
ImplFlags : [IL] [Managed] (00000000)
CallCnvntn: [DEFAULT]
ReturnType: Void
1 Arguments
Argument #1: I4
1 Parameters
(1) ParamToken : (08000002) Name : parameter flags: [Optional] [HasDefault] (00001010) Default: (I4) 5
Method #3 (06000003)
-------------------------------------------------------
MethodName: TestMethod2 (06000003)
Flags : [Private] [Static] [HideBySig] [ReuseSlot] (00000091)
RVA : 0x00002056
ImplFlags : [IL] [Managed] (00000000)
CallCnvntn: [DEFAULT]
ReturnType: Void
1 Arguments
Argument #1: I4
1 Parameters
(1) ParamToken : (08000003) Name : parameter flags: [Optional] [HasDefault] (00001010) Default: (I4) 5
That is the metadata of the two methods. We can see that the last line of each code section already has the default parameter value stored, so why is OptionalAttribute still referenced?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这可以被视为编译器中的错误。如果仔细检查程序集,就会发现没有任何内容引用OptionalAttribute TypeRef。
如果您没有明确添加 TestMethod2,TypeRef 将不会出现在生成的程序集中。这仅表明该属性在第一遍中添加,然后删除。它还表明编译器对 DefaultParameterValueAttribute 的处理方式有所不同。
最终,这确实是一个小的实现细节,例如,Mono 的 C# 编译器不会为生成的程序集中的任一属性生成 TypeRef。
This can be considered as a bug in the compiler. If you examine the assembly closely, there's nothing that references the OptionalAttribute TypeRef.
The TypeRef won't be present in the resulting assembly if you don't explicitely add in it TestMethod2. This simply shows that the attribute is added in a first pass, and later on removed. And it also shows that DefaultParameterValueAttribute is handled differently by the compiler.
Ultimately, this really is a small implementation detail, for instance, Mono's C# compiler won't produce a TypeRef for either attribute in the resulting assembly.