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