6

I have the following example:

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
        }
    }
}

The question is why in the second "Equals" call I'm redirected to Object.Equals instead of Hello.Equals even though I'm specifying the exact type in generic argument?

4

2 回答 2

11

因为你没有告诉你的对象实现的泛型方法IEquatable<T>

现在尝试:

private static bool ObjectsEqual<TValue>(TValue value1, TValue value2) 
               where TValue : IEquatable<TValue> // IMPORTANT!!!
{
    return value1.Equals(value2);
}

在您的ObjectsEqual方法中,您只能访问TValueobject类中定义的方法/属性/字段以及在约束中定义的接口/基类中定义的方法。没有约束 => 你只能访问Equals(object), GetHashCode(), GetType(), (如果你有约束class: operator==, operator!=。)这两个是虚拟的(Equals(object), GetHashCode()),所以你将使用“正确”版本,第三个通常不会被覆盖( GetType()),因此您可能会使用“正确”的版本。只有两个运算符==/!=经常被覆盖,你瞧!在您的通用方法中,您不能使用两者的“正确”版本!:-)

于 2013-09-06T12:24:33.110 回答
2

来自MSDN的补充

无界类型参数。
没有约束的类型参数(例如Tinpublic class SampleClass<T> { })称为无界类型参数
无界类型参数有以下规则:

  • 不能使用!=and==运算符,因为不能保证具体类型参数将支持这些运算符。
  • 它们可以相互转换System.Object或显式转换为任何接口类型。
  • 你可以比较一下null。如果将无界参数与 进行比较,则如果类型参数是值类型null,则比较将始终返回。false

在这种情况下TValue被转换为System.ObjectEquals调用方法。

于 2013-09-06T12:38:09.167 回答