CultureInfo中重要的InvariantCulture(转)

CultureInfo简述

CultureInfo类位于System.Globalization命名空间内,这个类和这个命名空间许多人都不了解也认为不需要太多了解,实际上,你写的程序中会经常间接得使用这些类。

简单的说:当进行数字,日期时间,字符串匹配时,都会进行CultureInfo的操作,也就是不同的CultureInfo下,这些操作的结果可能会不一样。这里要介绍一下非常容易被忽视的InvariantCulture。

通过示例了解InvariantCulture

前面提到过,不同的CultureInfo会影响某些函数的执行结果,.NET中有一个特殊的CultureInfo:InvariantCulture,这个CultureInfo有点像英语格式,但它不和国家地区挂钩,它可以提供一个可靠的在多语言环境下的规范格式化。

比如你编写一个程序,要向数据中心服务器传递一些时间数据,你会怎么写?直接DateTime.ToString()?那你就大错特错了,下面用代码,举个非常形象的例子。在一个控制台里,模拟数据中心,然后放出多个线程,模拟客户端程序传递数据。

  1. static readonly string[] CultureSources = { "en-us", "zh-cn", "ar-iq", "de-de" };
  2. static readonly Random Ran = new Random(Environment.TickCount);
  3. static void Main()
  4. {
  5. Console.WriteLine("数据中心开始接受客户端数据:");
  6. for (int i = 0; i < CultureSources.Length; i++)
  7. ThreadPool.QueueUserWorkItem(Client, i);
  8. Console.ReadKey(true);
  9. Console.WriteLine("");
  10. Console.WriteLine("数据中心:…………");
  11. }
  12. static void Client(object obj)
  13. {
  14. int id = (int)obj;
  15. Thread.Sleep(Ran.Next(1000));
  16. CultureInfo cul = CultureInfo.GetCultureInfo(CultureSources[id]);
  17. Thread.CurrentThread.CurrentCulture = cul;
  18. Console.WriteLine("某客户端操作系统语言设置{0}\n传送数据:{1}\n", cul.DisplayName, new DateTime(1990, 10, 27).ToShortDateString());
  19. }

运行结果:

结果看到了吧,同样的DateTime.ToShortDateString(),在英语-美国,中文-中国,阿拉伯语-伊拉克和德语-德国的不同环境下,1990年10月27日竟然有如此不同的输出结果,这些数据让数据中心服务器情何以堪啊……

原因则已提到过,在进行日期时间输出时,.NET会考虑当前线程的CultureInfo,即Thread.CurrentThread.CurrentCulture(或者CultureInfo.CurrentCulture),并根据CultureInfo,进行相应地区文化的数据处理。注意不要和UICulture混淆。

解决方案就是使用这个特殊的InvariantCulture。

把输出代码改成

  1. Console.WriteLine("某客户端操作系统语言设置{0}\n传送数据:{1}\n", cul.DisplayName,
  2. new DateTime(1990, 10, 27).ToString(
  3. CultureInfo.InvariantCulture.DateTimeFormat.ShortDatePattern, CultureInfo.InvariantCulture));

这样不管客户端运行在什么语言环境下,输出的时间格式都是统一的,方面数据中心服务器对数据做后续处理。

(当然这个例子仅用来演示InvariantCulture的用法,是否存在其他不妥处这里不做讨论)

InvariantCulture和字符串比较

下面代码进行四种字符串比较方法,分别是zh-cn, en-us文化,数值比较和InvariantCulture比较(全部是区分大小写)。

  1. static void Main()
  2. {
  3. string[] strs =
  4. { "a", "A", "b", "B", "abc", "ab", "aB", "AB", "Ab", "aaa", "00", "0001", "002", "a4", "a9", "a33" };
  5. Console.WriteLine("en-US");
  6. Array.Sort<string>(strs, StringComparer.Create(CultureInfo.GetCultureInfo("en-us"), false));
  7. Console.WriteLine(String.Join(" < ", strs));
  8. Console.WriteLine("zh-CN");
  9. Array.Sort<string>(strs, StringComparer.Create(CultureInfo.GetCultureInfo("zh-CN"), false));
  10. Console.WriteLine(String.Join(" < ", strs));
  11. Console.WriteLine("Ordinal");
  12. Array.Sort<string>(strs, StringComparer.Ordinal);
  13. Console.WriteLine(String.Join(" < ", strs));
  14. Console.WriteLine("Invariant");
  15. Array.Sort<string>(strs, StringComparer.InvariantCulture);
  16. Console.WriteLine(String.Join(" < ", strs));
  17. }

结果:

  1. en-US
  2. 00 < 0001 < 002 < a < A < a33 < a4 < a9 < aaa < ab < aB < Ab < AB < abc < b < B
  3. zh-CN
  4. 00 < 0001 < 002 < a < A < a33 < a4 < a9 < aaa < ab < aB < Ab < AB < abc < b < B
  5. Ordinal
  6. 00 < 0001 < 002 < A < AB < Ab < B < a < a33 < a4 < a9 < aB < aaa < ab < abc < b
  7. Invariant
  8. 00 < 0001 < 002 < a < A < a33 < a4 < a9 < aaa < ab < aB < Ab < AB < abc < b < B

(下面全部是区分大小写)

Ordinal是传统比较方式,即比较每个字符的数值,如果相等的话,继续比较下一组,如果有一个没有的话,长度大的算大。

Invariant和大多数CultureInfo都用一种更人性化的比较方法。首先判断一组字符是否是不一样(这里不区分大小写),直接返回结果如果不一样,因此b>AB,B>abc。如果一样的话比较下一组,如果都一样则比较长度,所以abc>AB>ab,如果长度都一样最后再比较大小写,另外一个字符大写永远大于小写,所以AB>Ab>aB>ab

那么InvariantCulture这样比较字符串有什么作用呢?我觉得这样输出形式可读性更高,其实InvariantCulture比较字符串就是先进行一次不区分大小写的Ordinal比较(不过这里大写字母>小写字母),如果结果不相同的话在进行一遍区分大小写的Ordinal比较(同样这里也是大写字母>小写字母)。这样可以将字符串先进行一次大的筛选,然后再比较细节,看下面的示例,Ordinal和InvariantCulture的比较结果可读性更高!

  1. string[] arr = { "Ab", "aB", "AB", "ab", "Abccccccc", "aBccccc", "Abd" };
  2. Array.Sort<string>(arr, StringComparer.Ordinal);
  3. Console.WriteLine(String.Join("\n", arr));
  4. Console.WriteLine();
  5. Array.Sort<string>(arr, StringComparer.InvariantCulture);
  6. Console.WriteLine(String.Join("\n", arr));

结果:

结果显而易见,Ordinal机器式的纯数值比较,上面的Ordinal排序结果看起来还是很乱,而InvariantCulture则可读性更高。

总结

支持多种CultureInfo是整个.NET Framework更加人性化,因为这可以使同一个数据适应不同地区和文化,这样当然满足处于不同地区和文化的用户,但前提是数据给“人”看,如果这些数据用于计算机之间的传输,即给“机器”看,这样的多文化处理反而不妥,造成同一个数据的不同展现形式,尤其是读写两方的文化地区不同时,数据可能根本无法被正常读取或者产生潜在bug,因此这里,正是InvariantCulture的用武之地

时间: 2024-08-25 07:39:44

CultureInfo中重要的InvariantCulture(转)的相关文章

CultureInfo.InvariantCulture 作用

Sql的处理经常会遇到拼sql的情况,将datetime拼到sql中以前的写法不统一,有直接写DateTime.ToString()的,有写DateTime.ToShortDateString(),还有DateTime.ToString("yyyy-MM-dd").总之,写法不一.这些方法都和Thread.CurrentThread.CurrentCulture有关系,这就是当前线程的文化.在应用程序启动时,会复制操作系统的区域设置到CurrentCulture中,直接导致了不同的问题

Resolve Type中构造函数传值

1 1 class Test 2 { 3 4 private ITeacher _teacher; 5 private IStudent _student; 6 public Test(ITeacher tea, IStudent stu) 7 { 8 _teacher = tea; 9 _student = stu; 10 } 11 } 2 1 class Student:IStudent 2 { 3 4 public Student() 5 { 6 int i = 1; 7 } 8 9 10

Asp.Net Web API 2第八课——Web API 2中的属性路由

参考页面: http://www.yuanjiaocheng.net/webapi/web-api-gaisu.html http://www.yuanjiaocheng.net/webapi/create-web-api-proj.html http://www.yuanjiaocheng.net/webapi/test-webapi.html http://www.yuanjiaocheng.net/webapi/web-api-controller.html http://www.yuan

ServiceStack.Text json中序列化日期格式问题的解决

标记: ServiceStack.Text,json,序列化,日期 在使用ServiceStack.Text的序列化为json格式的时候,当属性为datetime的时候,返回的是一个new date(324234234)的字符串,看着非常不爽. 如果是js来获取结果还好, 如果是c#获取这种字符串是没有办法转化为时间的. 所以我改造了下,让返回的是'2015-06-06 09:11:11'的格式. 先获取源码, 然后在jsconfig.cs中加入如下代码 Code Snippet private

如何在通用权限管理系统中集成log4net日志功能

开发人员都知道,在系统运行中要记录各种日志,自己写一个日志功能,无论是在效率还是功能扩展上来说都不是很好,目前大多用的是第三方的日志系统,其中一个非常有名,用的最多的就是log4net.下面是关于这个组件的介绍 ”Log4net是基于.net开发的一款非常著名的记录日志开源组件.最早是2001年7月由NeoWorks Limited启动的项目,基本的框架源, 于另外的一个非常著名的姐妹组件-log4j.现由Apache组织开发与维护.此日志架构是可灵活扩展,且通过配置文件来设置日志的属性及输出,

ASP.NET Web API中的参数绑定总结

ASP.NET Web API中的action参数类型可以分为简单类型和复杂类型. HttpResponseMessage Put(int id, Product item) id是int类型,是简单类型,item是Product类型,是复杂类型. 简单类型实参值从哪里读取呢?--一般从URI中读取 所谓的简单类型包括哪些呢?--int, bool, double, TimeSpan, DateTime, Guid, decimal, string,以及能从字符串转换而来的类型 复杂类型实参值从

【源码笔记】BlogEngine.Net 中的权限管理

BlogEngine.Net 是个功能点很全面的开源博客系统,容易安装和实现定制,开放接口支持TrackBack,可以定义主题配置数据源等等.可谓五脏俱全,这里先记录一下它基于Membership的权限管理(一般只说到角色就没了). Membership是.net2.0的时候就出来了,现在的最新版本是Identity(微软已经将这个Asp.net项目开源 https://github.com/aspnet/Identity ).权限管理就是处理用户.角色.和具体权限的关系.用户和角色是多对多的关

C#中 String 格式的日期时间 转为 DateTime

C#中并没有表示时间的变量,只有DateTime,所以要表示时间,可以用TimeSpan表示. 方法一:Convert.ToDateTime(string) string格式有要求,必须是yyyy-MM-dd hh:mm:ss 方法二:Convert.ToDateTime(string, IFormatProvider) DateTime dt; DateTimeFormatInfo dtFormat = new System.GlobalizationDateTimeFormatInfo();

在UWP中使用T4的注意事项

在UWP中尝试使用T4的朋友们可能会注意到,VS设计器默认生成的运行时T4无法通过编译,因为他使用了一些不支持UWP的API,解决方案也很简单,知道将其复制出来,修正不兼容的部分,指定inherits参数为新的基类即可,这里提供一个简单的版本,应该还可以优化 public class FormatterBase    {        private bool _endsWithNewline;        private StringBuilder _generationEnvironmen