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
,称为无界类型参数。
无界类型参数具有以下规则:

  • =
    =
    运算符,因为无法保证具体类型参数将支持这些运算符
  • 它们可以转换为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
就足够了。