有幾件事情正在進行。首先,在這個例子中:
string s1 = "a";
string s2 = "a";
Console.WriteLine(s1 == s2);
你聲稱:
兩者是不同的對象引用。
這不是真的,因爲字符串interning。s1
和s2
是對同一對象的引用。 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)
兩個問題:爲什麼把'd'轉換爲'object',因爲它已經是一個對象?另外,在'a Equals b'部分,我會調用對象覆蓋和字符串重載,所以更清楚它們之間的區別。 – doekman 2012-03-02 12:50:34
@doekman:1)是的,在這種情況下我不需要演員。 2)不確定你的意思。 – 2012-03-02 13:17:08
我的意思是:看最後一條。我沒有直接得到你的解釋超載/覆蓋.... – doekman 2012-03-02 13:35:39