使用默认参数带来的版本问题

来源:互联网 发布:c语言算法书籍推荐 编辑:程序博客网 时间:2024/05/16 06:10
默认参数在.net 3.0新增的内容,这是一个非常方便的内容,但是也可能带来意想不到的版本问题!!

新建一个程序集DefaultPara,里面的代码如下:

namespace DefaultPara{    public class SomeClass    {        public static int DefaultParaDemo(int a = 13)        {            return a;        }    }}

在另一个程序集的main中使用它,如下:

   static void Main(string[] args)        {           int result= DefaultPara.SomeClass.DefaultParaDemo();           Console.Write(result);           Console.Read();        }

全部编译,运行,输出13。OK~~

一切都没有问题,然后将他们发布到客户端。


现在需求变了,发现int a=13,不是一个好的默认值。打算将其修改为123。于是修改代码如下:

namespace DefaultPara{    public class SomeClass    {        public static int DefaultParaDemo(int a = 13)        {            return a;        }    }}

    然后单端编译这个程序集,将这个程序集重新发布到客户端!!或许会问,为什么不全部编译呢,因为在一个大的项目中,全部编译是需要时间的,同时也 不易于发布,因为客户要重新下载一个大大的程序。

   这时候,我们希望,main中输出的是123。但是,问题出现了,main中输出的却是13。这就是所谓的版本问题!!


为什么将默认值修改之后,就会出现版本问题呢,使用ILDasm查看一下main的方法就会发现,main中使用的是一个字面值13,而不是对变量a的引用。如下:

.method private hidebysig static void  Main(string[] args) cil managed  {    .entrypoint    // 代码大小       23 (0x17)    .maxstack  1    .locals init ([0] int32 result)    IL_0000:  nop    IL_0001:  ldc.i4.s   13    IL_0003:  call       int32 [DefaultPara]DefaultPara.SomeClass::DefaultParaDemo(int32)    IL_0008:  stloc.0    IL_0009:  ldloc.0    IL_000a:  call       void [mscorlib]System.Console::Write(int32)    IL_000f:  nop    IL_0010:  call       int32 [mscorlib]System.Console::Read()    IL_0015:  pop    IL_0016:  ret  }

注意那条ldc.i4.s 13指令,指令使用的是字面值13,我们知道使用字面值可能会引用版本问题。这就是问题的所在,所有对于含有默认值方法的调用,都会直接使用字面值来当默认值。


解决办法是这样的,可以将默认值修改为类型的默认值,譬如值类型的默认值是0,引用类型的默认值是null。对于泛型类型参数,默认值是default(T),先将代码修改如下:

namespace DefaultPara{    public class SomeClass    {        public static int DefaultParaDemo(int a =0)        {            return a;        }    }}

这样就OK了,不会在引起版本问题,因为他本身就是参数的默认值。