GDS*_*GDS 6 c# overloading ambiguous implicit-cast
(试图找到一个总结问题的标题可能是一项非常艰巨的任务!)
我有以下类与一些重载方法,产生一个调用歧义编译器错误:
public class MyClass
{
public static void OverloadedMethod(MyClass l) { }
public static void OverloadedMethod(MyCastableClass l) { }
//Try commenting this out separately from the next implicit operator.
//Comment out the resulting offending casts in Test() as well.
public static implicit operator MyCastableClass(MyClass l)
{
return new MyCastableClass();
}
//Try commenting this out separately from the previous implicit operator.
//Comment out the resulting offending casts in Test() as well.
public static implicit operator MyClass(MyCastableClass l)
{
return new MyClass();
}
static void Test()
{
MyDerivedClass derived = new MyDerivedClass();
MyClass class1 = new MyClass();
MyClass class2 = new MyDerivedClass();
MyClass class3 = new MyCastableClass();
MyCastableClass castableClass1 = new MyCastableClass();
MyCastableClass castableClass2 = new MyClass();
MyCastableClass castableClass3 = new MyDerivedClass();
OverloadedMethod(derived); //Ambiguous call between OverloadedMethod(MyClass l) and OverloadedMethod(MyCastableClass l)
OverloadedMethod(class1);
OverloadedMethod(class2);
OverloadedMethod(class3);
OverloadedMethod(castableClass1);
OverloadedMethod(castableClass2);
OverloadedMethod(castableClass3);
}
public class MyDerivedClass : MyClass { }
public class MyCastableClass { }
Run Code Online (Sandbox Code Playgroud)
有两个非常有趣的事情需要注意:
这自然会带来两个问题:
OverloadedMethod(MyClass l, MyClass r))中解决违规调用,因为MyDerivedClass它与MyClasscastable 更密切相关,但在其他方面无关紧要MyCastableClass.VS重构似乎也同意这种直觉.编辑:
在玩了VS重构之后,我看到VS将违规方法调用与代码中定义的第一个重载相匹配.因此,如果我们交换两个重载VS,则将违规调用与具有MyCastableClass参数的一个进行匹配.这些问题仍然有效.
什么是编译器错误背后的逻辑(即编译器如何达到歧义)?
首先,我们必须确定方法组中的方法.显然,方法组中有两种方法.
其次,我们必须确定这两种方法中哪一种适用.也就是说,每个参数都可以隐式转换为相应的参数类型.显然,这两种方法都适用.
第三,鉴于存在多种适用方法,必须确定唯一的最佳方法.在只有两个方法,每个只有一个参数的情况下,规则是从参数到参数类型的转换必须优于另一个.
关于什么使一次转换比另一种转换更好的规则在规范的7.5.3.5节中,为方便起见,我在这里引用:
给定从类型S转换为类型T1的转换C1,以及从类型S转换为类型T2的转换C2,如果存在以下至少一个,则C1是比C2更好的转换:
•存在从S到T1的身份转换,但不存在从S到T2的身份转换
•T1是比T2更好的转换目标
给定两种不同类型T1和T2,如果至少有以下一种情况,则T1是比T2更好的转换目标:
•存在从T1到T2的隐式转换,并且不存在从T2到T1的隐式转换
此规则的目的是确定哪种类型更具体.如果每个香蕉都是水果而不是每个水果都是香蕉,那么香蕉比水果更具特色.
•T1是带符号的整数类型,T2是无符号整数类型.
在列表中运行.是否有身份转换MyDerivedClass为?MyCastableClass或MyClass?不是.是否存在隐式转换MyClass,MyCastableClass而不是隐式转换?没有.没有理由认为任何一种类型都比另一种更具体.是整体类型?没有.
因此,没有任何依据可以确定一个人比另一个人更好,因此这是不明确的.
这个设计有什么问题吗?
问题回答了自己.你发现了其中一个问题.
直观地说,应该没有歧义,并且应该在第一个方法重载中解决违规调用,因为MyDerivedClass与MyClass关系更密切
虽然这对您来说可能很直观,但在这种情况下,规范并未区分用户定义的转换和任何其他隐式转换.但是我注意到,在一些罕见的情况下,你的干扰确实很重要 ; 有关详细信息,请参阅我关于链式用户定义转换的文章.(http://blogs.msdn.com/b/ericlippert/archive/2007/04/16/chained-user-defined-explicit-conversions-in-c.aspx)
| 归档时间: |
|
| 查看次数: |
785 次 |
| 最近记录: |