![](/img/trans.png)
[英]What is the "best" canonical implementation of Equals() for reference types?
[英]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
很特殊。 它按順序執行以下步驟,直到獲得一些結果:
obj
比較為'null',則返回false
。 this
和obj
參數是不同的類型,則返回false
。 true
。 Equals
配對實例字段。 如果這些字段中的任何一個不相等,則返回false
。 否則返回true
。 請注意,它從不調用基本方法Object.Equals
。 因為它使用反射來比較字段,所以應始終在您創建的任何ValueType
上重寫 Equals
。 反思很慢。
當它是“GCReference”或結構中作為參考類型的字段時,它會在每個字段上使用反射進行比較。 它必須這樣做,因為struct
實際上有一個指向引用類型在堆上的位置的指針。
如果結構中沒有使用引用類型,並且它們是相同的類型,則保證字段的順序相同,並且內存中的大小相同,因此它只能比較裸存儲器。
對於僅具有字段值類型的結構,即只有一個int
字段的結構,在比較期間不進行反射。 沒有字段引用堆上的任何內容,因此沒有GCReference
或GCHandle
。 此外,此結構的任何實例都將具有相同的字段內存布局(有一些小的例外),因此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.