C#关于参数为null(空值)的方法调用,重载顺序选择彻底研究
2008-09-24 13:43
513 查看
其实这是一个很老的问题了,很久以前就在园子里看到有人对此迷惑,当时也没太在意,觉得哪会有人那么写代码。直到最近丁学君的这篇文章:“关于参数为可空值类型的多个重载的优先级”才让我对这个问题重新有了兴趣。并且做出了一个大胆的猜想,现在这个猜想已经被我验证了。
所有具备单向隐式类型转换或者存在继承关系的类型的方法重载,当使用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中也采用类似的规则,这一点有待装配脑袋的确认。
所有具备单向隐式类型转换或者存在继承关系的类型的方法重载,当使用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中也采用类似的规则,这一点有待装配脑袋的确认。
相关文章推荐
- 关于JAVA继承类的静态变量、成员变量、父子类构造方法调用顺序的研究
- 关于 Spring AOP 中,包含参数的成员方法的调用,出现 NoSuchMethodException 的研究
- java调用Kotlin方法的参数为null异常问题
- js实现调用方法(函数)时可动态传入不同参数个数、模拟实现方法(函数)重载
- 关于参数为可空值类型的多个重载的优先级 (彻底晕掉了)
- (转)Delphi 调用C#编写的WebService 参数为Null解决方法 附中文乱码问题
- Atitit.通过null 参数 反射 动态反推方法调用
- Delphi 调用C#编写的WebService 参数为Null解决方法
- Delphi 调用C#编写的WebService 参数为Null解决方法
- 关于Java中方法调用时参数的传递
- Delphi (c++builder) 调用C#编写的WebService 参数为Null解决方法
- Java重载,当参数为null时,调用情况
- 认真CS丨方法调用、方法重载、命名参数
- 关于子类调用父类构造方法的研究
- 关于java的反射,调用私有方法(有参数私有方法),私有属性
- 关于Java中方法调用时参数的传递
- 关于Java中方法调用时参数的传递
- [Java]关于Null面对两个重载构造的选择的小题目
- java 重载 多个方法的调用顺序
- 关于java重载函数,参数为null时,调用的处理。(精确性原则)