我有一个类会覆盖加法运算符两次。一个采用type参数,一个采用double:
public class A<T>
{
public A() { }
public static A<T> operator +(A<T> a, T t)
{
Console.WriteLine("Generic add called.");
return new A<T>(); // return to keep the compiler happy
}
public static A<T> operator +(A<T> a, double d)
{
Console.WriteLine("Double add called.");
return new A<T>(); // return to keep the compiler happy
}
}
当类由int
类型参数化时,它的行为符合预期:
A<int> aInt = new A<int>();
var test = aInt + 3;
// -> Generic add called.
test = aInt + 3.0;
// -> Double add called.
但是,当double
类型参数化时,会调用非泛型添加:
A<double> aDouble = new A<double>();
var otherTest = aDouble + 3.0;
// -> Double add called.
假设这种行为是常态,我知道会调用哪种行为。非通用覆盖将是首选。那说......
在发生碰撞时,是否始终首选非通用方法?
上述所有代码均可在您的浏览器中运行,here
编辑:This question是相关的,但是它询问的是通用方法,而不是类。他给出了这段代码:
class A
{
public static void MyMethod<T>(T myVal) { }
public static void MyMethod(int myVal) { }
}
不适用于我的使用示例。区分a.MyMethod(3)
和a.MyMethod<int>(3)
是显而易见的 - 一个是通用的,一个不是。
答案 0 :(得分:0)
简单回答是的。编译器假设因为您手动处理了特定的类型参数,这意味着它有一些特殊的逻辑。这就是调用第二个运算符的原因。更进一步说,运算符只不过是接受某些参数的静态方法。对于你的情况,它是一个二元运算符,所以静态方法有两个参数。
答案 1 :(得分:0)
将选择更具体的方法,但这种结构是一个坏主意,因为它是技术上未指明的行为。
引用@EricLippert,将代码片段替换为我的问题:
但是[
aDouble + 3.0
]的情况要糟糕得多。 CLR规则使这种情况“实现定义的行为”,因此任何旧的事情都可能发生。从技术上讲,CLR可以拒绝验证构造类型[A<double>
]的程序。或者它可能崩溃。事实上它既没有;在糟糕的情况下,它能做到最好。是否有这种类型构造的例子导致真正的实现定义行为?
是。有关详细信息,请参阅这些文章:
http://blogs.msdn.com/b/ericlippert/archive/2006/04/05/odious-ambiguous-overloads-part-one.aspx
http://blogs.msdn.com/b/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx