zoukankan      html  css  js  c++  java
  • 翻译:重载解决和Null

    原文:http://msmvps.com/blogs/Senthil/
    Overload resolution and null
    最近在努力学习英语,所以决定自己来翻译一些c#和.NET相关的技术文章,既可学习英语,又能学习到c#和.NET的技术,可谓是一举两得的事情。如果翻译不到位,请谅解,也希望能得到大家友善的指正。

    我的同事Soundar发现一个相当有趣的行为
     1: class Test
      2: {
      3:     public static void Main()
      4:     {
      5:         Test test = null;
      6:
      7:         Console.WriteLine("{0}", test);
      8:         Console.WriteLine("{0}", null);
      9:     }
     10: }

    如果你运行上面代码,你就会发现第7行打印了一空行,而第8行导致了一个ArgumentNullException异常。注意test的引用也是null,所以这会令你惊讶,因为运行时这两行不一样的行为。

    它当然也让我惊讶并使我非得深究导致区别的原因不可。我认为相同的参数值在同样的运行时,产生了不同的结果,是因为编译器的操作——可能是方法重载。果然,第7行和第8行要求不同的重载来解决。

    第7行使用了下面重载
    public static void WriteLine(string format, object arg0);
    第8行使用了下面重载
    public static void WriteLine(string format, params object[] arg);

    使用Reflector查看IL代码显示当arg为null时第二种重载会抛出异常,而第一种重载会把arg0转变成一个对象数组,并要求第二种重载。

    然而,为什么编译器会现在两种不同的重载呢?
    直观地,当只传入一个参数给调用方法时,你期望重载机制会更倾向于选择单个参数的重载,而不是可变参数的重载。这就是编译器对第七行选择重载一的原因。
    在第八行的情况不一样,null直接分配给参数arg0和arg,重载机制必须选择最好的函数,这个时候它选择了参数为对象数组的重载方法。
    这显得和直观相反,直到你拥有类似下面的代码:
    1: class Test
      2: {
      3:     public static void Main()
      4:     {
      5:         SubTest subTest = null;
      6:         M(subTest);
      7:     }
      8:
      9:     static void M(Test t) { Console.WriteLine("Test"); }
     10:     static void M(SubTest s) { Console.WriteLine("SubTest"); }
     11: }
     12:
     13: class SubTest : Test { }
    你不会感到惊讶运行到第六行时是要求重载方法M(SubTest),你会吗?
    在C#规范的规则里确定最好的匹配是这样说的:
    “给出一个从类型S转换为T1的隐形转换C1和一个从类型S转换为T2的隐形转换C2,这两个转换方式中选择哪个最好有下面的几点决定:
    (1)如果类型T1和类型T2相同,两种转换性能一样。
    (2)如果S是T1类型,则C1是更好的转换。
    (3)如果S是T2类型,则C2是更好的转换。
    (4)如果存在类型T1向类型T2隐性转换,并且不存在T2向T1的隐形转换,那么C1是更好的转换方法。
    (5)如果存在类型T2向类型T1隐性转换,并且不存在T1向T2的隐形转换,那么C2是更好的转换方法。
    ....”
    在上面代码中,SubTest(T1)可以隐性地转换为Test(T2),所以编译器选择了M(SubTest).
    在我们的代码中,编译器努力在null转换为对象object和null转换为数组object[]中选择最好的转换方式,根据上面的转换原则,object[]能隐性地转换为object,所以重载机制选择了WriteLine(string format, params object[] arg). 在解决null参数的案例中,修饰的参数并没有发挥作用。
    非常有趣?是不是呢?

  • 相关阅读:
    SQLite-SQLiteDatabase 数据库实例练习
    全局配置一个ajax的错误监控
    文件上传&&验证文件格式
    CSS3 resize 属性
    select change()
    window.location.Reload()和window.location.href 区别
    条件检索
    jQuery $.ajax传递数组的traditional参数传递必须true 对象的序列化
    jquery中attr方法和prop方法的区别
    resize
  • 原文地址:https://www.cnblogs.com/zoupeiyang/p/1544350.html
Copyright © 2011-2022 走看看