控制面板設置小數點和數字分組符合後容易引起的bug

先了解一下通過CultureInfo.CurrentUICulture和CultureInfo.InvariantCulture與控制面板設置的關係
控制面板設置如圖
這裏寫圖片描述

   public partial class Form1 : Form
    {
        public Form1()
        {
            System.Globalization.CultureInfo cuf1 = CultureInfo.Currentulture;//資源管理器使用的當前區域性以便在運行時查找區域性特定的資源
            System.Globalization.CultureInfo cuf2 = CultureInfo.InvariantCulture;//不依賴於區域性(固定)的對象。
            List<CultureInfo> listCuf = new List<CultureInfo>() {cuf1, cuf2 };

            string str = string.Empty; 
            foreach (var c in listCuf)
            {
                str += c.TextInfo.ListSeparator+" "+ c.NumberFormat.NumberDecimalSeparator+" "+ c.NumberFormat.NumberGroupSeparator+" ";
                // str 爲 | , 。 , . ,    可以看到 CurrentUICulture是獲取的控制面板的設置,  InvariantCulture  則是自己默認的                    
            }
            ///ListSeparator屬性是有set的,但是如果執行cuf1.TextInfo.ListSeparator = "?"  給ListSeparator賦值,會拋異常:實例爲只讀
            ///  其實反編譯找到下面的方法 可以看到 能不能賦值是有條件的,不滿足條件就拋出異常
            /// private void VerifyWritable()
            /// {
            ///     if (this.m_isReadOnly)
            ///     {
            ///         throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
            ///      }
            ///  }
            ///   這種new的CultureInfo對象就可以給ListSeparator屬性賦值,原因也是在反編譯裏可以看到
            ///   NumberFormatInfo nfi = new CultureInfo("en-US", false).NumberFormat
            ///   nfi.TextInfo.ListSeparator = " ?";
        }
    }

下面是可能拋異常的情況.

//一般大家都是ToString(),其實等同於ToString(CultureInfo.CurrentCulture),ToDouble同理
double d1 = 3.3; //首先明確 ASP.NET裏數值類型還是“.”表示的小數點,CultureInfo裏NumberDecimalSeparator是體現在字符串上

string s1 = d1.ToString(CultureInfo.CurrentCulture); //s1=3!3  控制面板設置的是 "!" 爲小數點 ,所以這裏字符串爲3!3
string s2= d1.ToString(CultureInfo.InvariantCulture);//s1=3.3   CultureInfo.InvariantCulture 是 "." 表示小數點,所以字符串是3.3

double d2 = Convert.ToDouble(s1, CultureInfo.CurrentCulture);//d2=3.3  CultureInfo.CurrentCulture能識別 "!" 所以成功轉爲3.3
double d3 = Convert.ToDouble(s1, CultureInfo.InvariantCulture);//// 拋異常: 輸入字符串的格式不正確 CultureInfo.InvariantCulture裏沒有"!",識別不了

double d4 = Convert.ToDouble(s2,CultureInfo.CurrentCulture);//拋異常: 輸入字符串的格式不正確。 CultureInfo.InvariantCulture裏沒有"!",識別不了
double d5 = Convert.ToDouble(s2,CultureInfo.InvariantCulture);//d5=3.3 CultureInfo.InvariantCulture能識別"." 所以成功轉爲3.3

//可以看出s1由d1 ToString時參數爲CultureInfo.CurrentCulture , ToDouble時必須要 CultureInfo.CurrentCulture,s2同理
//所以如果轉爲string還是轉回double ,ToString()和ToDoubl()的參數須保持一致,不然會拋異常   
//只是一般情況控制面板設置的恰好與  CultureInfo.InvariantCulture時一致的,所以沒有拋出異常           

下面是數值可能不正確的情況

double d1 = 3.3; 
string s1 = d1.ToString(CultureInfo.CurrentCulture); //s1=3,3

double d3 = Convert.ToDouble(s1, CultureInfo.InvariantCulture);//d3=33 ,因爲","在InvariantCulture是數字分組符號,數字分組符合只是爲了方便肉眼看出數的位數或者大小,並不影響數值大小,所以這裏會轉化成33

最後舉一個例子


  //假如有需求是一個數由整數位和小數位拼接而來,而我們的習慣肯定是用"."拼接.
   int a = 10;
   int b = 26;
   double c= Convert.ToDouble(a + "." + b);    
   //控制面板裏沒有"." 會拋異常. 將數字分組符號設爲"." c=1026 都會有問題

所以建議中間過程ToString()和ToDoubl()時都用上CultureInfo.InvariantCulture參數來避免用戶更改控制面板設置而引發bug,最後要顯示到控件上用CultureInfo.CurrentCulture。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章