簡體   English   中英

C#運算符==:什么是標准做法(參考/值相等)?

[英]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將在第一個(但不是第二個)操作數上執行虛擬調度,並根據該對象的運行時類型查找方法的實現。 ==運算符是完全靜態綁定的; 它僅考慮兩個操作數的編譯時類型。 除了綁定方面的差異之外,兩者都具有相同的默認行為,並且都可以重寫兩者以提供所需的任何實現。

標准做法是始終確保Equalsoperator ==的行為與您的類型相同。 如果您重寫Equals方法來更改相等語義,則還應該重載==運算符以提供* identified語義,反之亦然。

問題是,通常是否可以覆蓋operator ==來測試值的相等性

這取決於對象,如果對象是不可變的,則可以覆蓋==運算符,否則不可以。 (請記住,它們只是准則)

請參見: 重寫Equals()和運算符==的准則(C#編程指南)

默認情況下,運算符==通過確定兩個引用是否指示同一對象來測試引用是否相等。 因此,引用類型不必實現運算符==即可獲得此功能。 當類型是不可變的時 ,即實例中包含的數據無法更改時, 重載運算符==以比較值相等性而不是引用相等性可能會很有用,因為作為不可變對象,它們可以視為長因為它們具有相同的價值。 在非不可變類型中覆蓋運算符==不是一個好主意。

賦予代碼語義是一個好習慣。 因此,如果引用比較確實是您應該關心的事情,請對類使用默認行為; 否則,應使用與應用程序上下文相關的邏輯進行比較。 (具有所有相等成員(如EqualsGetHashCode和operator)的一致行為)

暫無
暫無

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

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