原 c# 参数约束原理

2018-05-17 16:03:15 浏览数 (2)

 针对此问题的探索来源于我们通常使用的默认参数,类似于

代码语言: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

此时需要在程序中反射使用该特性。

0 人点赞