针对此问题的探索来源于我们通常使用的默认参数,类似于
代码语言:javascript复制void NullTest(String str1, string str2 = "default")
这种形式的代码经常使用。开始我猜测是某种语法糖的实现,然而查阅资料后发现和我想的不一样。
url链接http://stackoverflow.com/questions/5497514/what-does-opt-mean-in-msil
首先反编译
代码语言:javascript复制.method public hidebysig instance void NullTest(string str1,
[opt] string str2) cil managed
{
.param [2] = "default"
// 代码大小 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method Program::NullTest
由opt和param指令可以看出这并非是语法糖而是由metadata支持的功能。事实上这种写法只是一种简写形式
完整的写法应该是如下形式
代码语言:javascript复制void NullTest2(String str1, [Optional, DefaultParameterValue("default")]string str2)
反编译的形式和上面的完全相同。
这里用到了两个特性标记(OptionalAttribute和DefaultParameterValueAttribute),这两个特性是clr底层支持,写在Param table中,结合生成的il代码,提供了参数约束的能力,类似的还有
不同的标记可能会存储一些数据到元数据中如default,也有可能在编译中提供功能标记,如in和out。
此外可以使用自定义特性,
代码语言:javascript复制 [AttributeUsage(AttributeTargets.Parameter)]
public class MyTestAttribute : Attribute
{
}
反编译如下
代码语言:javascript复制 [MyTest2]
private void NullTest3(String str1, [MyTest]string str2)
{
}
.method private hidebysig instance void NullTest3(string str1,
string str2) cil managed
{
.param [2]
.custom instance void NullParatweTest.MyTestAttribute::.ctor() = ( 01 00 00 00 )
// 代码大小 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method Program::NullTest3
此时需要在程序中反射使用该特性。