具有覆盖方法的通用 class - 哪个被调用?
Generic class with overridden method - which gets called?
我有一个 class 覆盖加法运算符两次。一个采用类型参数,一个采用双精度参数:
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
}
}
当 class 被 int
类型参数化时,它的行为符合预期:
A<int> aInt = new A<int>();
var test = aInt + 3;
// -> Generic add called.
test = aInt + 3.0;
// -> Double add called.
但是当被 double
类型参数化时,非泛型 add 被调用:
A<double> aDouble = new A<double>();
var otherTest = aDouble + 3.0;
// -> Double add called.
假设这种行为是常态,我知道哪个会被调用。非通用覆盖将是首选。也就是说...
在发生冲突时,非泛型方法是否总是首选?
以上所有代码均可用,可在您的浏览器中运行,here
编辑:This question 是相关的,但它询问的是通用 方法 ,而不是 classes。他给出了这个代码:
class A
{
public static void MyMethod<T>(T myVal) { }
public static void MyMethod(int myVal) { }
}
不适用于我的用法示例。 a.MyMethod(3)
和 a.MyMethod<int>(3)
之间的区别很明显 - 一个是通用的,一个不是。
简单回答是。编译器假设因为您已经手动处理了一个特定的类型参数,这意味着它有一些适合您的特殊逻辑。这就是调用第二个运算符的原因。进一步说,运算符无非是接受一些参数的静态方法。对于您的情况,它是一个二元运算符,因此静态方法有两个参数。
将选择更具体的方法,但该构造不是一个好主意,因为它在技术上是未指定的行为。
引用 @EricLippert,用我的问题中的代码片段代替:
But the situation with [aDouble + 3.0
] is far worse. The CLR rules make this sort of situation "implementation defined behaviour" and therefore any old thing can happen. Technically, the CLR could refuse to verify a program that constructs type [A<double>
]. Or it could crash. In point of fact it does neither; it does the best it can with the bad situation.
Are there any examples of this sort of type construction causing truly implementation-defined behaviour?
是的。有关详细信息,请参阅这些文章:
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
我有一个 class 覆盖加法运算符两次。一个采用类型参数,一个采用双精度参数:
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
}
}
当 class 被 int
类型参数化时,它的行为符合预期:
A<int> aInt = new A<int>();
var test = aInt + 3;
// -> Generic add called.
test = aInt + 3.0;
// -> Double add called.
但是当被 double
类型参数化时,非泛型 add 被调用:
A<double> aDouble = new A<double>();
var otherTest = aDouble + 3.0;
// -> Double add called.
假设这种行为是常态,我知道哪个会被调用。非通用覆盖将是首选。也就是说...
在发生冲突时,非泛型方法是否总是首选?
以上所有代码均可用,可在您的浏览器中运行,here
编辑:This question 是相关的,但它询问的是通用 方法 ,而不是 classes。他给出了这个代码:
class A
{
public static void MyMethod<T>(T myVal) { }
public static void MyMethod(int myVal) { }
}
不适用于我的用法示例。 a.MyMethod(3)
和 a.MyMethod<int>(3)
之间的区别很明显 - 一个是通用的,一个不是。
简单回答是。编译器假设因为您已经手动处理了一个特定的类型参数,这意味着它有一些适合您的特殊逻辑。这就是调用第二个运算符的原因。进一步说,运算符无非是接受一些参数的静态方法。对于您的情况,它是一个二元运算符,因此静态方法有两个参数。
将选择更具体的方法,但该构造不是一个好主意,因为它在技术上是未指定的行为。
引用 @EricLippert,用我的问题中的代码片段代替:
But the situation with [
aDouble + 3.0
] is far worse. The CLR rules make this sort of situation "implementation defined behaviour" and therefore any old thing can happen. Technically, the CLR could refuse to verify a program that constructs type [A<double>
]. Or it could crash. In point of fact it does neither; it does the best it can with the bad situation.Are there any examples of this sort of type construction causing truly implementation-defined behaviour?
是的。有关详细信息,请参阅这些文章:
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