先了解一下通過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。