簡體   English   中英

== 或 .Equals()

[英]== or .Equals()

為什么要使用一個?

== 是身份測試。 如果被測試的兩個對象實際上是同一個對象,它將返回 true。 Equals()執行相等測試,如果兩個對象認為自己相等,則返回 true。

身份測試速度更快,因此您可以在不需要更昂貴的相等性測試時使用它。 例如,與null或空字符串進行比較。

可以重載其中任何一個以提供不同的行為——比如Equals()身份測試——但為了任何人閱讀你的代碼,請不要這樣做。


下面指出:某些類型(如StringDateTime==運算符提供重載,使其具有相等語義。 因此,確切的行為將取決於您正在比較的對象的類型。


也可以看看:

@約翰米利金:

下面指出:一些值類型(如 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.

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