來個.NET隨堂測驗,請解釋以下現象:
在以上程式,bool test = d["A"] == "1"所得結果為true,代表二者相等;但由Immediate Window顯示d["A"] == "1"卻是false,為什麼?
首先聲明: d["A"] == "1"的寫法有問題! d的型別為Dictionary<string, object>,故d["A"]所傳回型別為object,對object進行==運算時,等同Object.ReferenceEuals(),只有當前後二者指向同一物件時才會傳回true。由MSDN對於 == 運算子的說明:
- 對於預先定義的實值型別 (Value Type),等號比較運算子 (==) 在運算元相等時傳回 true;否則傳回 false。
- 對於 string以外的參考型別,若兩個運算元參考到同一物件,== 會傳回 true。
- 對於 string 型別,== 會比較字串的值。
程式的原意是要做字串比較,卻忽略了d["A"]傳回的是object,當與"1"比較,內部進行的是Object.ReferenceEquals() [適用上述第2點]。在這個例子中,正確的做法是將d["A"]轉型為string再進行 == 比對,比較的才是二者的字串內容。
事實上,針對這類不適當的 == 使用,Visual Studio會提出警告: (只是警告而非錯誤,程式可編譯、執行)
Possible unintended reference comparison; to get a value comparison, cast the left hand side to type 'string'
很好,我們已指出d["A"] == "1"寫法不當,只有二者指向同一物件時才會得到true。在實測中,Immediate Window檢測d["A"] == "1"為false可以被理解,但test = d["A"] == "1"卻得到true,又是怎麼一回事?
這要從字串常值(String Literal)說起,本草綱目MSDN有記載:
字串常值的型別是
string
。
每個字串常值並不一定會產生新的字串執行個體 (Instance)。依據字串相等運算子 (章節 7.9.7),當兩個或是多個相等的字串常值出現在相同組件時,這些字串常值便會參考到相同的字串執行個體。
由此可知,程式碼裡出現兩次"1",編譯器會讓兩個"1"字串常值指向同一個字串執行個體,在此情況下,d["A"]與"1"將會指向同一個字串執行個體,Object.ReferenceEquals()傳回true,==運算子的執行結果為true。而在Immediate Window操作所輸入的"1",由於是偵錯期間動態編譯執行,故會指向另外的字串執行個體,故==比對得到false。
解題完畢,大家答對了嗎?