为什么这不起作用?(通用等于助手)

B3r*_*ret 3 c# generics equals

解决了! 这个工作,我需要告诉编译器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>
{....
Run Code Online (Sandbox Code Playgroud)

题:

我试图将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);
    }
Run Code Online (Sandbox Code Playgroud)

想法是:d1.Equals(d2obj)调用Dummy.Equals(对象)调用EqualsHelper.secureEquals(T,obj)调用EqualsHelper.secureEquals(T,T)调用Dummy.Equals(Dummy).

然而,最后一个调用调用Dummy.Equals(object),即使在那里输入了所有内容.

我错过了什么?

PS:我知道用以下方式替换呼叫:

            if (!((IEquatable<T>)obj1).Equals(obj2)) //this calls Dummy.Equals(object other)!
Run Code Online (Sandbox Code Playgroud)

诀窍,但为什么不工作呢?

Mar*_*ell 5

原因:因为这里的方法调用是静态类型的,并且唯一可用的Equals涉及T没有通用约束的是object.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);
}
Run Code Online (Sandbox Code Playgroud)