假设两个类具有以下隐式和显式运算符模式:
class Foo
{
public static implicit operator decimal (Foo foo)
{
throw new NotImplementedException();
}
public static implicit operator Foo (decimal value)
{
throw new NotImplementedException();
}
public static Foo operator +(Foo left, Foo right)
{
throw new NotImplementedException();
}
}
class Bar
{
public static explicit operator decimal (Bar bar)
{
throw new NotImplementedException();
}
public static explicit operator Foo(Bar bar)
{
throw new NotImplementedException();
}
}
现在考虑以下代码:
var foo = new Foo();
var bar = new Bar();
var resultFooAddBar = foo + (decimal)bar;
隐式输入resutlFooAddBar
解析为Foo
,添加运算符解析为Foo Foo.operator +
。为什么这段代码没有出现含糊不清的错误?运营商可以平等地解决decimal decimal.operator +
。是因为用户定义的运算符总是被认为更合适吗?即便如此,选择似乎有点奇怪,考虑到Bar
有一个明确的强制转换为Foo
未使用哪个将明确定义程序员想要使用的运算符:
var resultFooAddBar = foo + (Foo)bar;
//好的,我明确说我要Foo Foo.operator +
如果我们使用定义decimal
的第三个类Tango
以及相同的隐式和显式运算符模式而不是Tango Tango.operator + (Tango, Tango)
,那么编译器会抛出一个不明确的调用错误。
为什么区分用户定义的运算符和非用户定义的运算符?
更新:我已经创建了一个单独的程序集,包括以下类来试用Servy的exlanation:
namespace ExternalAssembly
{
public class Tango
{
public static Tango operator +(Tango left, Tango right)
{
throw new NotImplementedException();
}
}
}
然后在decimal
和Tango
中将Foo
更改为Bar
,并将所需的引用添加到ExternalAssembly dll。在这种情况下,我仍然得到' +'操作员对操作数不明确&#;; ConsoleApplication.Foo'和' ExternalAssembly.Tango' 。在这种情况下,为什么编译器不会选择与Foo Foo.operator +
原始问题中相同的重载decimal
?
答案 0 :(得分:1)
重载分辨率算法具有一系列优点"它们用于确定应该使用方法/运算符的多个适用重载的度量。只有当这些指标中没有一个具有最终的“最佳”时,才会出现这种情况。超载,显示出歧义错误。
更好的衡量指标之一是"亲密度"有问题的重载定义到呼叫站点。同一类中的定义是"更接近"除了它之外的定义,外部类中的定义比该父类型之外的定义更接近,同一名称空间中的定义比外部命名空间中的定义更接近等等。您的定义是“更接近”。比小数的+
运算符。 (有关该主题的更多信息,请参阅this article。)