[英]C# operator== : what is standard practice (reference/value equality)?
說明:
Equals()
比較兩個對象的值。 ReferenceEquals()
比較它們的引用。 對於引用類型, operator==
默認情況下會比較引用,而對於值類型,它將執行(AFAIK)使用反射的Equals()等效項。
所以。 我有一種情況,我需要按它們的值比較兩個引用類型。 我可以顯式調用Equals()
,也可以重載operator==
來執行所需的比較。
但是,對於值比較而言,重載operator==
有點違反了最小驚訝原則。 另一方面,顯式調用兩個對象的Equals
看起來像是過分殺傷。
這里的標准做法是什么?
我知道如何重寫Equals()
。 問題是,是否可以覆蓋operator==
來測試引用類型上的值相等性,還是普遍接受的做法是顯式調用Equals / ReferenceEquals來顯式指定所需的比較。
什么是標准做法?
“標准做法”是,如果要檢查兩個元素的相等性(不是引用相等性),則需要實現IEquatable<T>
,它引入了Equals(T other)
方法,並重寫GetHashCode
。 這樣, 您可以控制比較這兩個對象的方式。 通常,這還包括覆蓋==
和!=
運算符。
而對於值類型,它使用反射執行(AFAIK)等效於Equals()。
僅當您的值類型具有作為引用類型的成員時。 如果都是值類型, 它將對這兩個對象進行一些比較 :
// 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);
問題是,通常是否可以覆蓋operator ==來測試引用類型上的值相等性
這實際上取決於您在做什么。 鼓勵您在重寫Equals
重寫==
運算符,因為您想要一致的行為值相等語義。 這取決於您對兩個對象之間相等性的定義。
雖然,如果一個對象是可變的,那么進行值比較可能會導致奇怪的情況,其中兩個對象被認為是相等的,但后來,一個對象就被突變了。 絕對應該根據具體情況對此進行分析。 通常,重載Equals
就足夠了。
Equals()
執行兩個對象的值比較。
這不是真的。 object.Equals
的默認行為是使用字段的相等性定義比較每個字段,引用類型的默認行為是比較它們的引用。 做任何您想做的事都可以被覆蓋。 在這方面,它與==
運算符完全相同。
==
運算符和Equals
之間的唯一區別是, Equals
將在第一個(但不是第二個)操作數上執行虛擬調度,並根據該對象的運行時類型查找方法的實現。 ==
運算符是完全靜態綁定的; 它僅考慮兩個操作數的編譯時類型。 除了綁定方面的差異之外,兩者都具有相同的默認行為,並且都可以重寫兩者以提供所需的任何實現。
標准做法是始終確保Equals
和operator ==
的行為與您的類型相同。 如果您重寫Equals
方法來更改相等語義,則還應該重載==
運算符以提供* identified語義,反之亦然。
問題是,通常是否可以覆蓋operator ==來測試值的相等性
這取決於對象,如果對象是不可變的,則可以覆蓋==
運算符,否則不可以。 (請記住,它們只是准則) 。
請參見: 重寫Equals()和運算符==的准則(C#編程指南)
默認情況下,運算符==通過確定兩個引用是否指示同一對象來測試引用是否相等。 因此,引用類型不必實現運算符==即可獲得此功能。 當類型是不可變的時 ,即實例中包含的數據無法更改時, 重載運算符==以比較值相等性而不是引用相等性可能會很有用,因為作為不可變對象,它們可以視為長因為它們具有相同的價值。 在非不可變類型中覆蓋運算符==不是一個好主意。
賦予代碼語義是一個好習慣。 因此,如果引用比較確實是您應該關心的事情,請對類使用默認行為; 否則,應使用與應用程序上下文相關的邏輯進行比較。 (具有所有相等成員(如Equals
, GetHashCode
和operator)的一致行為)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.