zoukankan      html  css  js  c++  java
  • C#关于参数为null(空值)的方法调用,重载顺序选择彻底研究

    其实这是一个很老的问题了,很久以前就在园子里看到有人对此迷惑,当时也没太在意,觉得哪会有人那么写代码。直到最近丁学君的这篇文章:“关于参数为可空值类型的多个重载的优先级”才让我对这个问题重新有了兴趣。并且做出了一个大胆的猜想,现在这个猜想已经被我验证了。

    所有具备单向隐式类型转换或者存在继承关系的类型的方法重载,当使用null值调用时,将会使用隐式类型转换的方向来确定调用哪个方法。

    简而言之,假设TypeA和TypeB之间存在一个隐式类型转换或者继承关系,方向是TypeA对象可以隐式转换为TypeB(TypeA存在一个到TypeB的隐式类型转换或者TypeA派生于TypeB)。

    又有两个方法的重载如下:

    public void MyMethod( TypeA obj ){ … }//重载A

    public void MyMethod( TypeB obj ){ … }//重载B

    那么MyMethod( null )一定会选择重载A。

    但是这还没完,我仔细测定了各种情况的调用情况,并和装配脑袋一起分析整理了一下,还有如下结论:

    1、对于Nullable<T>类型而言,T所拥有的运算符(包括隐式类型转换运算符)都会被投射到T?类型。比如说,int有一个隐式类型转换到long,那么int?也就会自动存在一个隐式类型转换到long?。同样的,TypeA?也有一个隐式类型转换到TypeB?(如果TypeA和TypeB是值类型)。这就解释了丁学文章中所说的问题。

    2、如果两个类型之间存在双向的隐式类型转换,即TypeA可以隐式类型转换为TypeB,而TypeB也可以隐式类型转换为TypeA,这种情况下,使用null值调用会是一个编译错误。推广开来,如果多个类型之间存在一个闭环的隐式类型转换,比如说TypeA->TypeB,TypeB->TypeC,TypeC->TypeA,那么如果这三个类型的重载都存在的话,使用null值调用同样的编译错误,但是如果只有两个类型的重载存在(即方法重载的参数类型不存在闭环)那么也不会有错误。

    3、数组的协变也会被看作是一个隐式类型转换,比如说TypeA派生于TypeB,则TypeA[]存在一个到TypeB[]的隐式转换,这个被称之为数组的协变。那么这个隐式转换也会被这个规则采信,即如果两个方法的参数是TypeA[]和TypeB[]的话,采用null值调用会选择TypeA[]的重载。

    4、VB中也采用类似的规则,这一点有待装配脑袋的确认。

  • 相关阅读:
    第十三章 类继承
    第十一章 使用类
    第十章 对象和类
    第九章 内存模型和名称空间
    第八章 函数幽探
    史上最详细得虚拟机安装过程,傻瓜式操作
    JVM内存结构图表展示
    主流消息队列rocketMq,rabbitMq比对使用
    springboot+druid+mybatis plus的多数据源配置
    linux服务器开放防火墙和端口,以及查询状态
  • 原文地址:https://www.cnblogs.com/Ivony/p/1297907.html
Copyright © 2011-2022 走看看