C# 为什么;等于;泛型的方法解析不同于显式调用
我举了以下例子:C# 为什么;等于;泛型的方法解析不同于显式调用,c#,comparison,method-resolution-order,C#,Comparison,Method Resolution Order,我举了以下例子: namespace ComparisonExample { class Program { static void Main(string[] args) { var hello1 = new Hello(); var hello2 = new Hello(); // calls Hello.Equals var compareExp
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
}
}
}
名称空间比较示例
{
班级计划
{
静态void Main(字符串[]参数)
{
var hello1=newhello();
var hello2=newhello();
//打电话给你好,平等
var compareExplicitly=hello1.Equals(hello2);
//调用对象。等于
var compareWithGenerics=ObjectsEqual(hello1,hello2);
}
私有静态布尔对象sequal(TValue值1,TValue值2)
{
返回值1.等于(值2);
}
}
同学你好:我可以
{
公共布尔等于(你好,其他)
{
return true;//没关系
}
}
}
问题是为什么在第二个“Equals”调用中,我被重定向到Object.Equals而不是Hello.Equals,即使我在泛型参数中指定了确切的类型?,因为您没有告诉泛型方法您的对象实现了
IEquatable
:
请立即尝试:
private static bool ObjectsEqual<TValue>(TValue value1, TValue value2)
where TValue : IEquatable<TValue> // IMPORTANT!!!
{
return value1.Equals(value2);
}
private static bool ObjectsEqual(TValue-value1,TValue-value2)
其中TValue:IEquatable//重要!!!
{
返回值1.等于(值2);
}
在ObjectsEqual
方法中,您只能访问TValue
类中定义的方法/属性/字段,以及约束中定义的接口/基类中定义的方法。无约束=>您只能访问Equals(object)
,GetHashCode()
,GetType()
,(如果您有约束类
:操作符==
,操作符!=
),这两个都是虚拟的(Equals(object)
,GetHashCode()
),因此您将使用“正确”版本,第三个通常不会被覆盖(GetType()
),因此您可能会使用“正确”的版本。只有两个运算符==
/=代码>经常被覆盖,瞧!在泛型方法中,不能使用这两种方法的“正确”版本:-) 添加自:
无界类型参数。
没有约束的类型参数,例如公共类SampleClass{}
中的T
,称为无界类型参数。
无界类型参数具有以下规则:
=无法使用code>和=
运算符,因为无法保证具体类型参数将支持这些运算符
- 它们可以转换为System.Object,也可以从System.Object转换为System.Object,或者显式转换为任何接口类型
- 您可以与
null
进行比较。如果将无界参数与null
进行比较,则如果类型参数是值类型,则比较将始终返回false
在这种情况下,TValue
被转换为System.Object
并调用Equals
方法。因为Equals的签名是bool Equals(Object other)
?你甚至都没有超越Equals(并且错过了override
关键字)。这并不是你问题的答案,但为什么不只是public override bool Equals(object other){return Equals(other as Hello);}
?因为我不想在GetHashCode方面遇到麻烦?TValue的o_ONo约束,因此等于Object。有趣的是,如果我指定TValue:IEquatable的位置,我仍然得到Object.Equals。但您的答案是正确的,其中TValue:IEquatable起作用job@username我要补充一点,在.NET库中,当他们想要比较泛型类型时,他们会做EqualityComparer.Default.Equals(T,T)
TValue:IEquatable
表示签名bool Equals(Hello other)
,在泛型中,您需要bool Equals(TValue other)
@VladimirFrolov明白了,所以我需要where TValue:Hello,IEquatable
来让这个特定的例子生效。where TValue:IEquatable
或者where TValue:Hello
就足够了。