为什么不起作用?(Generic Equals Helper)

本文关键字:Equals Helper Generic 不起作用 为什么 | 更新日期: 2023-09-27 18:19:29

已解决这是有效的,我需要告诉编译器T当然实现了IEquatable。。。

public static bool secureEquals<T>(T obj1, object obj2)
    where T: class, IEquatable<T>
{...
public static bool secureEquals<T>(T obj1, T obj2)
    where T: class, IEquatable<T>
{....

问题:

我试图将IEquatable实现和Equals重写的重复功能放入一个单独的静态类中,比如:

public static class EqualsHelper
{
    public static bool secureEquals<T>(T obj1, object obj2)
       where T : class
    {
        if (obj2 is T)
        {
            return secureEquals(obj1, obj2 as T);
        }
        else
        {
            return false;
        }
    }
    public static bool secureEquals<T>(T obj1, T obj2)
    {
        if (obj1 == null)
        {
            if (obj2 != null)
                return false;
        }
        else
        {
            if (!obj1.Equals(obj2)) //this calls Dummy.Equals(object other)!
                return false;
        }
        return true;
    }

    public static bool secureEquals(double[] obj1, double[] obj2)
    {
        if (obj1.Length != obj2.Length)
            return false;
        for (int i = 0; i < obj1.Length; ++i)
        {
            if (obj1[i] != obj2[i])//ok for doubles if they are generated in the same way? I guess so!
                return false;
        }
        return true;
    }
public class Dummy : IEquatable<Dummy>
{
    public Dummy(string member)
    {
        _member = member;
    }
    private string _member;

    public virtual bool Equals(Dummy other)
    {
        return this._member == other._member;
    }
    public override bool Equals(object other)
    {
        return EqualsHelper.secureEquals(this, other);
    }
}
    static void Main(string[] args)
    {
        Dummy d1 = new Dummy("Hugo");
        Dummy d2 = new Dummy("Hugo");
        object d2obj = (object)d2;
        bool ret = d1.Equals(d2obj);
    }

当时的想法是:d1.Equals(d2obj)调用Dummy。Equals(object)调用EqualsHelper。secureEquals

然而,最后一个调用Dummy.Equals(对象),即使所有内容都被键入为T。

我错过了什么?

PS:我知道用代替呼叫

            if (!((IEquatable<T>)obj1).Equals(obj2)) //this calls Dummy.Equals(object other)!

有诀窍,但为什么它不起作用呢?

为什么不起作用?(Generic Equals Helper)

原因:因为这里的方法invoke是静态类型的,而唯一可用的涉及没有泛型约束的TEqualsobject.Equals(object)。完全相同的IL必须能够处理每个T-C#泛型不像C++模板;则不会出现per-T过载解决方案。

顺便说一句:您可能还想看看EqualityComparer<T>.Default.Equals(obj1,obj2),它将自动处理IEquatable<T>Nullable<T>等:

public static bool secureEquals<T>(T obj1, object obj2) where T : class
{
    return EqualityComparer<T>.Default.Equals(obj1, obj2 as T);
}

EqualsHelper.secureEquals中的Equals重载在编译EqualsHelper时得到解决,并且该代码不知道T是否实现IComparable<T>,所以只剩下Equals(Object)。您可以向T添加一个约束,使其使用正确的重载:

public static bool SecureEquals<T>(T obj1, T obj2) where T : IEquatable<T>

当然,这会限制你可以使用它的类

(顺便说一句,我已经将secureEquals重命名为SecureEquals,以符合.NET命名约定。我个人也不会在这里使用"安全"一词——这里没有任何安全敏感的内容。)

因为在secureEquals中没有约束,编译器总是假设Object.Equals存在。为T.添加接口约束