簡體   English   中英

在.NET 4.0中,值類型的Equals的默認實現是什么?

[英]In .NET 4.0, What is the default implementation of Equals for value types?

這兩個文檔頁面似乎與此主題相矛盾:

它是按位平等還是反思?

ValueType的源代碼,發現了一條評論說

//如果此對象中沒有GC引用,我們可以避免反射

//並做一個快速的memcmp

有人可以澄清“GC參考”的含義嗎? 我想這是一個有引用類型的字段,但我不確定。

如果我創建一個只有值類型字段的struct ,它的實例總是會以快速的方式進行比較嗎?

更新: .Net 4.5的文檔已得到顯着改進:它沒有提到的矛盾,現在可以更好地理解默認值類型相等性檢查的工作原理。

System.ValueType.Equals很特殊。 它按順序執行以下步驟,直到獲得一些結果:

  1. 如果obj比較為'null',則返回false
  2. 如果thisobj參數是不同的類型,則返回false
  3. 如果類型是“blittable”,它會比較內存圖像。 如果它們相同,則返回true
  4. 最后,它使用反射為每個值調用Equals配對實例字段。 如果這些字段中的任何一個不相等,則返回false 否則返回true 請注意,它從不調用基本方法Object.Equals

因為它使用反射來比較字段,所以應始終在您創建的任何ValueType重寫 Equals 反思很慢。

當它是“GCReference”或結構中作為參考類型的字段時,它會在每個字段上使用反射進行比較。 它必須這樣做,因為struct實際上有一個指向引用類型在堆上的位置的指針。

如果結構中沒有使用引用類型,並且它們是相同的類型,則保證字段的順序相同,並且內存中的大小相同,因此它只能比較裸存儲器。

對於僅具有字段值類型的結構,即只有一個int字段的結構,在比較期間不進行反射。 沒有字段引用堆上的任何內容,因此沒有GCReferenceGCHandle 此外,此結構的任何實例都將具有相同的字段內存布局(有一些小的例外),因此CLR團隊可以進行直接內存比較(memcmp),這比其他選項快得多。

所以,是的,如果您的結構中只有值類型,它將執行更快的memcmp,而不是反射比較,但您可能不想這樣做。 繼續閱讀。

並不意味着您應該使用默認的Equals實現。 事實上,不要這樣做。 停下來。 它正在進行比較,這並不總是准確的。 你說的是什么? 讓我演示給你看:

private struct MyThing
{
    public float MyFloat;
}

private static void Main(string[] args)
{
    MyThing f, s;
    f.MyFloat = 0.0f;
    s.MyFloat = -0.0f;

    Console.WriteLine(f.Equals(s));  // prints False
    Console.WriteLine(0.0f == -0.0f); // prints True
}

數字在數學上是相等的,但它們的二進制表示不相等。 所以,我會再次強調它, 不要依賴ValueType.Equals的默認實現

不是這個領域的真正專家我會繼續並提出我的想法:文檔(據我所知)指出,如果你的結構有一個對象(引用類型)的字段,則無法避免反射。

所以如果你有以下內容:

    public struct SomeStruct
    {
        public object ObjectTest
    }

沒有反射就無法比較ObjectTest。 因此將使用反射。 這部分內容似乎說我是對的:

ValueType.Equals - Equals方法的默認實現使用反射來比較obj和此實例的相應字段。”

暫無
暫無

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

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