为什么泛型的“等于”方法解析与显式调用不同
本文关键字:调用 泛型 等于 方法 为什么 | 更新日期: 2023-09-27 18:30:35
我有以下示例:
namespace ComparisonExample
{
class Program
{
static void Main(string[] args)
{
var hello1 = new Hello();
var hello2 = new Hello();
// calls Hello.Equals
var compareExplicitly = hello1.Equals(hello2);
// calls Object.Equals
var compareWithGenerics = ObjectsEqual<Hello>(hello1, hello2);
}
private static bool ObjectsEqual<TValue>(TValue value1, TValue value2)
{
return value1.Equals(value2);
}
}
class Hello : IEquatable<Hello>
{
public bool Equals(Hello other)
{
return true; // doesn't matter
}
}
}
问题是为什么在第二个"等于"调用中,即使我在泛型参数中指定了确切的类型,我也会被重定向到 Object.Equals 而不是 Hello.Equals?
因为你还没有告诉泛型方法你的对象实现IEquatable<T>
:
立即试用:
private static bool ObjectsEqual<TValue>(TValue value1, TValue value2)
where TValue : IEquatable<TValue> // IMPORTANT!!!
{
return value1.Equals(value2);
}
在 ObjectsEqual
方法中,您只能访问在 object
类中定义的方法/属性/TValue
字段,以及在约束中定义的接口/基类中定义的方法。没有约束 =>您只能访问Equals(object)
、GetHashCode()
、GetType()
、(如果您有约束class
:operator==
、operator!=
。其中两个是虚拟的(Equals(object)
,GetHashCode()
),所以你会使用"正确"的版本,第三个通常不会被覆盖(GetType()
),所以你可能会使用"正确"的版本。只有两个运算符==
/!=
经常被覆盖,瞧!在您的通用方法中,您不能使用两者的"正确"版本!:-)
来自 MSDN 的添加:
无界类型参数。
没有约束的类型参数(如public class SampleClass<T> { }
中的T
)称为无界类型参数。
无界类型参数具有以下规则:
- 不能使用
!=
和==
运算符,因为无法保证具体类型参数将支持这些运算符。 - 它们可以与
System.Object
相互转换,也可以显式转换为任何接口类型。 - 您可以与
null
进行比较.如果将无界参数与null
进行比较,则比较将始终返回false
如果类型参数是值类型。
在这种情况下,TValue
将转换为System.Object
并调用Equals
方法。