我和我的朋友正在討論關於Dotnet框架中的字符串,他們是如何引用類型但行爲如值類型(不可變)。我們都知道CLR是內部的字符串,但是我們並沒有真正在這個簡短的討論中得出結論,CLR /框架如何創建和管理字符串。如何在CLR中創建和管理字符串?
例如,在下面的代碼顯然是s1
和s2
是不同的實例,但你可以看到,當我做s2.ToUpper()
結果指回s1
。
public static void Main (string[] args)
{
string s1 = "HELLO";
string s2 = "hello";
Console.WriteLine (s1.GetHashCode()); //Prints 68624562
Console.WriteLine (s2.GetHashCode()); //Prints 99162322
Console.WriteLine (s2.ToUpper().GetHashCode()); //Prints 68624562 too!
}
所以,這些問題是關於調用s2.ToUpper()
做了CLR創建新的字符串"HELLO"
,並檢查它已經存在,如果是這樣那麼扔掉新創建的字符串?有人能解釋這裏的魔法嗎?
不同的字符串實例可以(會)返回相同的散列碼(即你的代碼並不表明它們是不同的實例)。 – 2012-04-08 17:45:49
我對此沒有太多的瞭解,但我可以想象CLR只是執行ToUpper(),返回值臨時存儲在堆棧(?)上,並在其上應用GetHashCode()。如果你詢問哈希本身,那一切都OK - GetHashCode()是從字符串/另一個對象的* content *生成的。所以兩個相等字符串的哈希值是相同的。它用於平等測試。 – 2012-04-08 17:48:06
字符串以及其他不可變的引用類型**不會像值類型**那樣操作。永恆不變只會帶走你可以用可變引用類型做的一些事情(主要是通過在一個地方對它們進行變異並檢查另一個地方的變化來觀察它們是同一個對象),但是仍然有很多不同之處。假設'var arr = T [] {obj,obj}',用你選擇的值和引用類型試試'ReferenceEquals(arr [0],arr [1])''。 – delnan 2012-04-08 18:45:11