Wednesday, July 25, 2012

[C#] Specify a culture in string conversion explicitly

再來寫一個reSharper的建議,在某些轉型的狀況下,像是 Int 與 String 間的互轉,reSharper會跳出類似這樣 Specify a culture in string conversion explicitly 的建議,基本上就是提醒你這個轉型方式在某些語系設定下,可能會產生問題,當然如果你確定你的程式不會遇到語系問題,就可以忽略掉它,不過我個人還是會去確保程式的正確性,不然到時候出問題就難搞了。

關於ASP.NET的語系問題,你大概都可以在文化特性 CultureInfo 類別 這邊找到答案,不同的語系設定,會影響到的東西大致有四塊,分別是書寫系統大小寫(TextInfo 類別)、日期格式(DateTimeFormatInfo 類別)、數字格式(NumberFormatInfo 類別)與字串比較(CompareInfo 類別)。可以想像一下,你寫的一套系統,在不同國家的語系設定下,同一個時間點去轉出的日期字串居然長得不一樣....光想就覺得可怕,所以在轉型時必須去確保這點才行。



話不多說,直接來一段程式測試。
        static public string[] Arr = { "0", "1", "+1", "-1"};

        static void Main()
        {
            CultureInfo ci = Thread.CurrentThread.CurrentCulture;
            //ci = (CultureInfo)ci.Clone();
            //ci.NumberFormat.NegativeSign = "!";

            var t0 = new Thread(ThreadNum) {CurrentCulture = ci};
            t0.Start();

            Console.ReadLine();
        }
        
        static void ThreadNum()
        {
            Console.WriteLine(Thread.CurrentThread.CurrentCulture);
            foreach (var s in Arr)
            {
                Console.Write(s);
                Console.Write("=");
                Console.Write(Int32.Parse(s) + ", ");
            }
            Console.WriteLine();
        }
    }
跑出來的結果很簡單,就是把 String 轉成 Integer 而已。

Culture2

接下來就可以開始測試了。

為了不讓過程太複雜,我用改變語系的數字正負號顯示,來代替改變語系做測試,簡單很多但是精神上是一樣的。

把上面程式第六、七行的註解拿掉,再來跑一次,其中第七行是這次測試的目的,就是把這個語系的負號顯示符號改成驚嘆號,結果如下。

Culture

在"-1"這個字串要轉成整數時,因為前面已經把負號的符號改掉了,所以系統不認得"-"是啥,轉不成整數,於是發生錯誤,你可以想像當換了語系之後,也有可能會遇到這樣的情況,感覺就是個真的發生時會很難解的問題。

這時候呢,只要在轉型的地方加上CultureInfo.InvariantCulture 屬性,就可以避免這個問題,也就是在第22行轉型的地方,從 Int32.Parse(s) 改成 Int32.Parse(s,CultureInfo.InvariantCulture) ,就可以避免因語系導致轉型後資料不同的問題了,結果如下。

Culture3

可賀可喜,收工。

No comments:

Post a Comment