簡體   English   中英

結構包裝類型C#的默認相等比較

[英]Default Equality Comparison of Struct Wrapper types C#

C#參考指出,對於值類型:

ValueType.Equals(Object)方法將覆蓋Object.Equals(Object),並為.NET Framework中的所有值類型提供默認的值相等實現。

如果當前實例和obj的字段都不是引用類型,則Equals方法將對內存中的兩個對象進行逐字節比較。 否則,它將使用反射來比較obj和此實例的相應字段。

https://msdn.microsoft.com/zh-CN/library/2dts52z7(v=vs.110).aspx

既然這樣,因為int是一個值類型,所以我希望一個簡單的int包裝器就等於它包裝的int,因為在逐字節比較中它是相同的-它們都只包含一個int:

    public struct Id
    {
        public Id(int id)
        {
            Id = id;
        }
        public int Id { get; }
    }

    Console.WriteLine(new Id(17).Equals(17);

但是它實際上打印錯誤。 為什么是這樣?

這些不是同一類型。 盡管文本沒有明確說明,但Equals方法檢查它們是否為同一類型。

所以這可以工作:

new Id(17).Equals(new Id(17));

如果要在結構上處理兩種不同類型的比較,則需要重寫Equals並自己處理。

相關來源是:

public abstract class ValueType {
    [System.Security.SecuritySafeCritical]
    public override bool Equals (Object obj) {
        BCLDebug.Perf(false, "ValueType::Equals is not fast.  "+this.GetType().FullName+" should override Equals(Object)");
        if (null==obj) {
            return false;
        }
        RuntimeType thisType = (RuntimeType)this.GetType();
        RuntimeType thatType = (RuntimeType)obj.GetType();

        if (thatType!=thisType) {
            return false;
        }

        Object thisObj = (Object)this;
        Object thisResult, thatResult;

        // if there are no GC references in this object we can avoid reflection 
        // and do a fast memcmp
        if (CanCompareBits(this))
            return FastEqualsCheck(thisObj, obj);

        FieldInfo[] thisFields = thisType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

        for (int i=0; i<thisFields.Length; i++) {
            thisResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(thisObj);
            thatResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(obj);

            if (thisResult == null) {
                if (thatResult != null)
                    return false;
            }
            else
            if (!thisResult.Equals(thatResult)) {
                return false;
            }
        }

        return true;
    }

如您所見,它在檢查字節之前先驗證參數的類型是否匹配。 由於您的類型不是int ,因此它將始終返回false。

通常,即使兩個對象都封裝相同的值,對象的Equals方法也不會將其視為等於任何其他類型的對象。

由於重載,將某些類型的值傳遞給其他類型的Equals方法的行為可能導致它們轉換為與原始類型相同的類型。 例如, (16777216.0f).Equals(16777217)將選擇重載Equals(float) ,將int16777217轉換為最接近的float值(即16777216.0f ),后者將依次等於16777216.0f 可以通過將兩個操作數轉換為object來防止此行為,如((object)16777.216.0f).Equals(16777216)(16777.216.0f).Equals((object)16777216)中的任何一個都將報告一個float對象與int對象不相等(即使它們具有相同的數值)。

暫無
暫無

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

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