当我在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呢?
答案 0 :(得分:3)
这可以被视为编译器中的错误。如果仔细检查程序集,则没有任何引用OptionalAttribute TypeRef。
如果您没有明确地添加TestMethod2,则TypeRef将不会出现在生成的程序集中。这只是表明该属性是在第一遍中添加的,后来又被删除了。它还表明编译器对DefaultParameterValueAttribute的处理方式不同。
最终,这确实是一个小的实现细节,例如,Mono的C#编译器不会为生成的程序集中的任何一个属性生成TypeRef。