2012-03-02 89 views
17

==Equals()有什麼區別?我知道==用於比較運營商和Equals()方法用於比較string.So的內容我想C#中的==運算符和Equals()方法之間的區別?

// first example 
string s1 = "a"; 
string s2 = "a"; 
Console.Write(a.Equals(s2)); // returns true, but if I assign "b" to s2, 
          // then result will be false 

// second example 
string s1 ="a"; 
string s2 ="a"; 
Console.Write(s1 == s2);  // returns true 

怎麼會是這樣?兩者都是不同的對象引用。假設我們認爲這些是參考。但是我試圖用這樣

string s1 = new string("ab"); 
string s2 = new string("ab"); 

我正在編譯不能轉換時錯誤字符串從Equals文檔燒焦

回答

21

有幾件事情正在進行。首先,在這個例子中:

string s1 = "a"; 
string s2 = "a"; 
Console.WriteLine(s1 == s2); 

你聲稱:

兩者是不同的對象引用。

這不是真的,因爲字符串internings1s2是對同一對象的引用。 C#規範保證 - 來自C#4規範的2.4.4.5節:

當根據字符串相等運算符(§7.10.7)等效的兩個或更多個字符串文本出現在同一個程序中時,這些字符串文字引用相同的字符串實例。

因此,在這種特殊情況下,你仍然會得到「真正的」,即使你打印object.ReferenceEquals(s1, s2),或者如果你做它用與==真正的參考身份對比:即使

object s1 = "a"; 
object s2 = "a"; 
Console.WriteLine(s1 == s2); // Still prints True due to string literal interning 

然而,這些分別是對分開物體的引用,==超載對於string。重載是一個編譯時間的決定 - 使用的實現取決於操作數的編譯時類型。例如:

string a = new string('x', 1); 
string b = new string('x', 1); 
Console.WriteLine(a == b); // Uses string's implementation, prints True 

object c = a; 
object d = b; 
Console.WriteLine(c == d); // Reference identity comparison, prints False 

object.Equals(object)比較,這是一個虛擬的方法。碰巧,String重載此方法以及,但重要的是它覆蓋它。因此,如果我們我們的代碼更改爲:

string a = new string('x', 1); 
string b = new string('x', 1); 
Console.WriteLine(a.Equals((object) b)); 

object c = a; 
object d = b; 
Console.WriteLine(c.Equals(d)); 

...那麼這兩個方法在編譯的代碼調用只會是object.Equals(object),但他們會仍然兩個打印正確的,因爲多態性:在String實施將會被使用。

這裏給重載方法的調用將是什麼樣子:

string a = new string('x', 1); 
string b = new string('x', 1); 
Console.WriteLine(a.Equals(b)); // Calls string.Equals(string) 
+0

兩個問題:爲什麼把'd'轉換爲'object',因爲它已經是一個對象?另外,在'a Equals b'部分,我會調用對象覆蓋和字符串重載,所以更清楚它們之間的區別。 – doekman 2012-03-02 12:50:34

+0

@doekman:1)是的,在這種情況下我不需要演員。 2)不確定你的意思。 – 2012-03-02 13:17:08

+0

我的意思是:看最後一條。我沒有直接得到你的解釋超載/覆蓋.... – doekman 2012-03-02 13:35:39

7

報價:

的默認實現的Equals支持引用類型爲 的引用相等,以及值類型的按位相等。參考 相等意味着被比較的對象引用指的是同一對象的 。按位相等意味着被比較的對象具有相同的二進制表示。

== operator

對於預定義的值的類型,如果 的操作數的值相等,否則爲假相等運算符(==)返回true。對於參考 字符串以外的其他類型,如果其兩個操作數引用 相同的對象,則==返回true。對於字符串類型,==會比較 字符串的值。

回到你的問題:爲什麼s1 == s2返回true?字符串是.NET中的特殊動物。它們代表不可變的參考類型。他們在.NET中被執行。這意味着如果你有兩個具有相同值的字符串常量,它們將在運行時引用同一個對象實例。從documentation

報價:

公共語言運行庫通過維護 表節省字符串存儲,叫實習生池,包含一個參考 每一個獨特的文本字符串聲明或 編程方式創建你的程序。因此,具有 特定值的文字字符串的實例僅在系統中存在一次。

+0

由於實習,這不是*僅*。實習就是爲什麼即使他們被聲明爲'object'類型也會工作。但是,即使引用具有相同內容的不同字符串對象,只要涉及的編譯時類型都是字符串,就會由於運算符重載而起作用。你引用的文檔是誤導性的,因爲它暗示有一些特殊的處理*僅用於字符串* - 沒有,只​​是該字符串是* a *引用類型,它重載了==運算符。 – 2012-03-02 07:25:21

+1

另請注意,實習是一種語言細節 - 。NET提供了這種機制,但除非沒有字符串常量實習,否則很可能會有各種方式與C#相同的語言Dumb#。 – 2012-03-02 07:36:40

2

你想看起來的Java式的。在java中,==運算符不能自定義,因此對於引用類型,它總是意味着引用相等,而它意味着基本類型的值相等。另一方面,Equals用於檢查參考類型中的值相等性。

雖然C#中的事情有所不同。 Equals==都可以定製實現。不同之處在於Equals是一種虛擬(實例)方法,而operator==是一種靜態方法。除此之外,他們可以以完全相同的方式行事。

默認情況下,Equals==均檢查引用類型的引用相等性和值類型的值相等性。但是,對於string,都進行了自定義以檢查值相等。

相關問題