遇到奇妙的.NET程式庫版本參考錯誤。
試用以下專案重現問題,主專案RefIssue參照類別程式庫Blah專案:
Blah專案有一個TextId列舉,一個TextRes類別,提供靜態方法將TextId列舉轉換成字串。
namespace Blah
{
publicenum TextId
{
TextPattern,
MsgDismatch,
MsgAbout
}
publicclass TextRes
{
publicstaticstring GetText(TextId id)
{
switch (id)
{
case TextId.TextPattern:
return"[0-9A-Za-z]{1,6}";
case TextId.MsgDismatch:
return"不符要求";
case TextId.MsgAbout:
return"別讓黑大不開心";
}
returnstring.Empty;
}
}
}
RefIssue程式很單純,將字串"abc123"與TextId.TextPattern對應字串"[0-9A-Za-z]{1,6}"進行Reqular Expression比對,若格式不符則輸出TextId.MsgDismatch對應字串,符合時則輸出"OK"。在正常狀況下,應該要看到OK字樣。
using System;
using System.Text.RegularExpressions;
using Blah;
namespace RefIssue
{
class Program
{
staticvoid Main(string[] args)
{
string pwd = "abc123";
if (!Regex.IsMatch(pwd, TextRes.GetText(TextId.TextPattern)))
{
Console.WriteLine(TextRes.GetText(TextId.MsgDismatch));
}
else
{
Console.WriteLine("OK");
}
Console.Read();
}
}
}
下一步來玩點小把戲:將整個bin/Debug的檔案複製到Test資料夾,接著修改TextId列舉,在最前方增加一個新項目NewValue:
namespace Blah
{
publicenum TextId
{
NewValue, //在最前方插入資料
TextPattern,
MsgDismatch,
MsgAbout
}
publicclass TextRes
{
publicstaticstring GetText(TextId id)
{
switch (id)
{
case TextId.NewValue:
return"新資料";
case TextId.TextPattern:
return"[0-9A-Za-z]{1,6}";
case TextId.MsgDismatch:
return"不符要求";
case TextId.MsgAbout:
return"別讓黑大不開心";
}
returnstring.Empty;
}
}
}
重新編譯後,測試結果仍顯示OK,很合理。有趣的部分來了:將重新編譯的RefIssue.exe複製到Test資料夾覆寫舊檔,但Blah.dll不要更新,執行Test下的RefIssue.exe,猜猜會有什麼結果?
好笑吧? 程式顯示一段莫名其妙的訊息。
問題出在列舉編譯後會儲存成數值,當變更TextId列舉在前方插入新值,會使原本的第0個項目變成第1個,第1個變成第2個。重新編譯RefIssue.exe,TextId.TextPattern將等於1,TextId.MsgDismatch會存成2,此時配上舊版Blah.dll,TextId.TextPattern(1)被轉換成"不符要求",TextId.MsgDimatch(2)被轉換成"別讓黑大不開心",下場便是Regex比對失敗,傳回錯亂訊息。
原因不難理解,但第一次「遇到漏更新程式庫,系統沒當掉或產生Exception,而是跑出莫名其妙的結果」。很新鮮,筆記留念。