[英]== or .Equals()
為什么要使用一個?
== 是身份測試。 如果被測試的兩個對象實際上是同一個對象,它將返回 true。 Equals()
執行相等測試,如果兩個對象認為自己相等,則返回 true。
身份測試速度更快,因此您可以在不需要更昂貴的相等性測試時使用它。 例如,與null
或空字符串進行比較。
可以重載其中任何一個以提供不同的行為——比如Equals()
身份測試——但為了任何人閱讀你的代碼,請不要這樣做。
下面指出:某些類型(如String
或DateTime
為==
運算符提供重載,使其具有相等語義。 因此,確切的行為將取決於您正在比較的對象的類型。
也可以看看:
@約翰米利金:
下面指出:一些值類型(如 DateTime)為 == 運算符 > 提供了重載,使其具有相等語義。 所以確切的行為將取決於您正在比較的 >objects 的類型。
詳細說明:
DateTime 被實現為一個結構體。 所有結構都是 System.ValueType 的子級。
由於 System.ValueType 的子級位於堆棧上,因此沒有指向堆的引用指針,因此無法進行引用檢查,您必須僅按值比較對象。
System.ValueType 覆蓋 .Equals() 和 == 以使用基於反射的相等性檢查,它使用反射來比較每個字段的值。
因為反射有點慢,如果你實現自己的結構,覆蓋 .Equals() 並添加你自己的值檢查代碼很重要,因為這會快得多。 不要只調用 base.Equals();
其他人幾乎都涵蓋了你,但我還有一句忠告。 .Equals
,您會發現有人對他的生活(以及他所愛的人的生活)發誓說.Equals
更有效/更好/最佳實踐或其他一些教條路線。 我不能談論效率(好吧,好吧,在某些情況下我可以),但我可以談論一個會突然出現的大問題: .Equals
需要一個對象存在。 (聽起來很愚蠢,但它讓人們望而卻步。)
您不能執行以下操作:
StringBuilder sb = null;
if (sb.Equals(null))
{
// whatever
}
對我來說,也許對大多數人來說,很明顯,你會得到一個NullReferenceException
。 然而, .Equals
支持者忘記了這個小.Equals
。 當他們看到 NullRefs 開始彈出時,有些人甚至被“拋棄”(抱歉,無法抗拒)。
(在DailyWTF發布之前的幾年里,我確實與一個要求所有平等檢查都是.Equals
而不是==
。即使證明他的不准確也無濟於事。我們只是確保打破他的所有其他規則,以便從方法或屬性返回的引用都不是空的,最后它解決了。)
==通常是“身份”等於“對象a實際上與對象b在內存中完全相同的對象”。
equals() 表示對象在邏輯上相等(例如,從業務角度來看)。 因此,如果您正在比較用戶定義類的實例,並且您希望 Hashtable 之類的東西正常工作,通常需要使用和定義 equals()。
如果您有眾所周知的 Person 類,它具有屬性“Name”和“Address”,並且您想將此 Person 作為包含有關它們的更多信息的 Hashtable 的鍵,則需要實現 equals()(和 hash),以便您可以創建一個 Person 的實例並將其用作 Hashtable 中的鍵來獲取信息。
單獨使用 == ,您的新實例將不一樣。
Equals
和==
都可以重載,因此調用一個或另一個的確切結果會有所不同。 注意==
是在編譯時確定的,所以雖然實際的實現可能會改變,但使用哪個==
在編譯時是固定的,不像Equals
可以根據左側的運行時類型使用不同的實現。
例如string
對==
執行相等測試。
另請注意,兩者的語義可能很復雜。
最佳實踐是像這個例子一樣實現相等。 請注意,您可以根據您計划如何使用您的類來簡化或排除所有這些,並且struct
s 已經獲得了大部分。
class ClassName
{
public bool Equals(ClassName other)
{
if (other == null)
{
return false;
}
else
{
//Do your equality test here.
}
}
public override bool Equals(object obj)
{
ClassName other = obj as null; //Null and non-ClassName objects will both become null
if (obj == null)
{
return false;
}
else
{
return Equals(other);
}
}
public bool operator ==(ClassName left, ClassName right)
{
if (left == null)
{
return right == null;
}
else
{
return left.Equals(right);
}
}
public bool operator !=(ClassName left, ClassName right)
{
if (left == null)
{
return right != null;
}
else
{
return !left.Equals(right);
}
}
public override int GetHashCode()
{
//Return something useful here, typically all members shifted or XORed together works
}
}
根據MSDN :
在 C# 中,有兩種不同類型的相等:引用相等(也稱為標識)和值相等。 值相等是一般理解的相等的含義:它意味着兩個對象包含相同的值。 例如,兩個值為 2 的整數值相等。 引用相等意味着沒有要比較的兩個對象。 相反,有兩個對象引用並且它們都引用同一個對象。
...
默認情況下,運算符 == 通過確定兩個引用是否指示同一個對象來測試引用相等性。
該示例是因為類 DateTime 實現了 IEquatable 接口,該接口實現了“用於確定實例相等性的特定於類型的方法”。 根據MSDN 。
另一件需要考慮的事情:如果您從另一種語言訪問對象,== 運算符可能不可調用或可能具有不同的含義。 通常,最好有一個可以通過名稱調用的替代方法。
如果要表示比較對象的內容應該相等,則使用equals。 將 == 用於原始值,或者如果您想檢查被比較的對象是否是同一個對象。 For objects == 檢查對象的地址指針是否相同。
我已經看到 Object.ReferenceEquals() 用於想知道兩個引用是否引用同一個對象的情況
在大多數情況下,它們是相同的,因此為了清楚起見,您應該使用 ==。 根據微軟框架設計指南:
“務必確保 Object.Equals 和相等運算符具有完全相同的語義和相似的性能特征。” https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/equality-operators
但有時,有人會在不提供相等運算符的情況下覆蓋 Object.Equals。 在這種情況下,您應該使用 Equals 來測試值是否相等,並使用 Object.ReferenceEquals 來測試引用是否相等。
如果你對 Object 進行反匯編(例如通過 dotPeek),那么
public virtual bool Equals(Object obj)
被描述成:
// Returns a boolean indicating if the passed in object obj is
// Equal to this. Equality is defined as object equality for reference
// types and bitwise equality for value types using a loader trick to
// replace Equals with EqualsValue for value types).
//
所以,取決於類型。 例如:
Object o1 = "vvv";
Object o2 = "vvv";
bool b = o1.Equals(o2);
o1 = 555;
o2 = 555;
b = o1.Equals(o2);
o1 = new List<int> { 1, 2, 3 };
o2 = new List<int> { 1, 2, 3 };
b = o1.Equals(o2);
第一次 b 為真(對值類型執行相等),第二次 b 為真(對值類型執行相等),第三次 b 為假(對引用類型執行相等)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.