我发现 C# 4.0 中的“可选参数”特性非常有趣,所以我试图弄清楚它们是如何实现的。所以我写了一个这样的方法:
private static void A(int a = 5) { }
编译它,然后在 IL DASM 中反编译它,这是 IL 代码:
.method private hidebysig static void A([opt] int32 a) cil managed
{
.param [1] = int32(0x00000005)
// Code size 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method Program::A
它的元数据中有这个:
(1)ParamToken:(08000002)名称:a标志:[可选] [HasDefault](00001010)默认值:(I4)5
于是我顺着线索写了一个这样的方法:
private static void B([Optional, DefaultParameterValue(78)]int b) { }
编译再反编译,我发现C#编译器为方法A和B生成了几乎相同的MSIL代码(名字除外)。
我们可以看到 IL 代码中没有属性的迹象,感觉不对,所以我写了一个这样的自定义属性:
[AttributeUsage(AttributeTargets.Parameter)]
public class MyTestAttribute : Attribute
{
}
然后像这样在方法C中使用它:
private static void C([MyTest]int c) { }
编译然后反编译,哈哈,我发现了这个:
.method private hidebysig static void C(int32 c) cil managed
{
.param [1]
.custom instance void ConsoleApplication1.MyTestAttribute::.ctor() = ( 01 00 00 00 )
// Code size 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method Program::C
方法主体的第二行调用了我的自定义属性的 ctor。
所以这导致了我的怀疑:
- [选择] 是什么意思?我的意思是出现在方法A和B的参数前面的那个。
- 为什么方法 C 调用了应用于其参数的 Attribute 的构造函数,而方法 A 和 B 却没有?
- 我似乎在元数据中找不到任何 DefaultParameterValueAttribute 的迹象,但我可以找到 OptionalAttribute 和 MyTestAttribute。这是为什么?有什么我想念的吗?
提前致谢。