簡體   English   中英

為什么這不起作用? (通用等於助手)

[英]Why is this not working? (Generic Equals Helper)

解決了! 這個工作,我需要告訴編譯器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(對象)調用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)!

訣竅,但為什么不工作呢?

原因:因為這里的方法調用是靜態類型的,並且唯一可用的涉及沒有泛型約束的T Equalsobject.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時, EqualsHelperEquals重載被解析 - 並且該代碼不知道T是否實現IComparable<T> ,所以剩下的就是Equals(Object) 您可以向T添加約束,這將使其使用正確的重載:

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

當然,這會限制您可以使用它的類。

secureEquals ,請注意我已將secureEqualssecureEqualsSecureEquals以符合.NET命名約定。我也不會在這里使用“安全”這個詞 - 這里沒有任何安全敏感性。)

因為在secureEquals中沒有約束,編譯器總是假定存在Object.Equals。 為你的T添加界面約束

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM