同事反應給我的問題,程式裡有段寫法if (r["F"] == "Y")的判別結果很怪,Line by Line Debug時,r["F"]的內容是"Y"沒錯,用Command Window檢查或監看(r["F"] == "Y")的結果是true,但實際的流程卻跑到false的分支。

首先要聲明,r["F"] == "Y"的寫法是有問題的。Visual Studio.NET 2003會提出警告,指出不應該將object與string直接相比。但是有趣的地方在於,實際流程中的二者比對結果是不相等,但即時運算視窗檢測卻二者相等。

我本來怪罪這是VS.NET 2003的老Bug,於是寫了一小段程式做實驗,卻發現更好玩的狀況。下圖是在VS.NET 2003的測試結果,我使用Watch監看r["F"]=="Y"跟在程式中比對(r["Y"]=="Y")後存入Boolean的變數b,二者的結果都是true。與我同事程式中為false,監看為true的狀況不同。

同樣的程式搬到VS2008(後來再測試VS2005的結果與VS2008相同),結果大異其趣。監看r["F"]=="Y"為false, 程式中的比對結果則為true,跟同事程式中的結果剛好相反。

感覺上是Visual Studio在除錯模式下判定比對結果的邏輯與實際Runtime不同所致,但VS2003, VS2005, VS2008, 實際程式與測試Code的結果理不出頭緒。

我把用VS2008 Submit a Bug功能把這問題反應給MS,當天得到回覆說已將問題轉交RD研究。如果有進一步消息,再報給大家知。


Comments

# by rosbicn

有趣的问题。我这么猜测。用r["F"] == "Y"比较的其实不是字符串的内容,而是字符串的指针或者说字符串的地址,在程序中两边碰巧都用了"Y"进行赋值,这是个常数字符串。常数字符串是否具有相同的指针,这个看编译器的情况和当时编译环境而定,是不确实的。如果程序改成,String s = "Y"; t.Rows.Add(new object[] { s };,后面用f["F"] == s进行比较,那结果肯定是一样的。用r["F"] == "Y",不光用不同开发环境情况会不同,我猜想你在相同开发环境相同的计算机,但是不同的日子或心情去实验,也会不同。原因是,是否两个常数字符串用相同的地址本来就是随机的事情。

# by Johnny

呃... 這不是隨機不隨機的問題, 被比較的也不是兩個字串或位址指標。其實這是一個曲型的型別轉換的問題; 我覺得這件事很容易釐清 - r["F"] 型別是 Object, "Y" 型別是 String, 兩者來相比當然不會相等。但當你把值指定給 b 時, 預設的 Comparer 是用字串來相比的, 它自動把 r["F"] 轉換成字串, 兩者再來比較, 就相等了。要解決這種問題, 使用 ((string) r["F"] == "Y") 應該是比較正確的做法。

# by Johnny

呃... 這不是隨機不隨機的問題, 被比較的也不是兩個字串或位址指標。其實這是一個曲型的型別轉換的問題; 我覺得這件事很容易釐清 - r["F"] 型別是 Object, "Y" 型別是 String, 兩者來相比當然不會相等。但當你把值指定給 b 時, 預設的 Comparer 是用字串來相比的, 它自動把 r["F"] 轉換成字串, 兩者再來比較, 就相等了。要解決這種問題, 使用 ((string) r["F"] == "Y") 應該是比較正確的做法。

# by rosbicn

To Johnny: 原文中没有说进行类型转换,讨论的是如果没有类型转换时候出现的诡异情况。如果没有进行类型转换,object和string比较,比较的就是指针或者地址。文章并不在讨论如何解决这个问题,文章一开始就说了,这种写法是不好的。我们要讨论的是为什么不同的人会得出不同结果的问题。加上类型转换自然就不需要讨论了。

# by SGY

HI: 注意一下IDE說的Mesage Warning 5 Possible unintended reference comparison; to get a value comparison, cast the left hand side to type 'string' 相關問題http://delphi.ktop.com.tw/board.php?cid=30&fid=69&tid=93028 不過這跟VS無關析

Post a comment