C# 当一个派生类型作为参数传递时,双向隐式可转换类型的重载之间的调用不明确
(试图找到一个总结问题的标题可能是一项非常艰巨的任务!) 我有以下类,其中包含一些重载方法,这些方法会产生调用模糊编译器错误:C# 当一个派生类型作为参数传递时,双向隐式可转换类型的重载之间的调用不明确,c#,overloading,ambiguous,implicit-conversion,C#,Overloading,Ambiguous,Implicit Conversion,(试图找到一个总结问题的标题可能是一项非常艰巨的任务!) 我有以下类,其中包含一些重载方法,这些方法会产生调用模糊编译器错误: public class MyClass { public static void OverloadedMethod(MyClass l) { } public static void OverloadedMethod(MyCastableClass l) { } //Try commenting this out separately fro
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 { }
有两件非常有趣的事情需要注意:
OverloadedMethod(MyClass l,MyClass r)
)中解决有问题的调用,因为MyDerivedClass
与MyClass
的关系更为密切,而不是可浇铸的,但在其他方面与MyCastableClass
无关。此外,VS重构似乎符合这种直觉MyCastableClass
参数的调用相匹配。不过,这些问题仍然有效
编译器错误背后的逻辑是什么
嗯,编译器根据一些事情来确定签名。参数的数量和类型在名称旁边,这是最重要的参数之一。编译器检查方法调用是否不明确。它不仅使用参数的实际类型,而且还使用它可以隐式强制转换到的类型(请注意,显式强制转换是不存在的,这里不使用)
这就是你所描述的问题
这个设计有什么问题吗
对。模棱两可的方法是许多问题的根源。尤其是在使用变量类型时,如动态
。即使在这种情况下,编译器也无法选择调用哪个方法,这很糟糕。我们希望软件是确定性的,而有了这段代码,它就不可能是确定性的
你没有要求,但我想最好的选择是:
显式
强制转换而不是隐式
强制转换,使强制转换成为编译器可以理解的经过深思熟虑的选择MyDerivedClass
到MyCastableClass
或MyClass
的身份转换?否。是否存在从MyClass
到MyCastableClass
的隐式转换,但不是隐式转换?没有。没有理由认为这两种类型都比另一种更具体。是整型还是整型?没有
因此,没有什么可以作为一个比另一个更好的决定的基础,因此这是不明确的
这个设计有什么问题吗
问题本身就解决了。你发现了其中一个问题
直观地说,应该没有歧义,并且应该在第一个方法重载中解决有问题的调用,因为MyDerivedClass与MyClass的关系更密切
虽然这对您来说可能是直观的,但在这种情况下,规范没有区分用户定义的转换和任何其他隐式转换。然而,我注意到,在一些罕见的情况下,你的辨别能力确实很重要;有关详细信息,请参阅我的文章。()这两个问题都没有答案,但您关于是否需要两个重载的观点很有趣。不幸的是,在我的例子中,隐式强制转换和重载都是有意义的、有效的,而且我认为是必要的,即使你的观点让我更有效地编写重载。为什么你认为我的答案不能回答这些问题?如果
A=B
和B=A
,编译器在为A
和B
签名时应该选择什么