☰
.NET 字符串比较:Ordinal、InvariantCulture 和 Culture
2026/10/15 13:34:48 网站建设 项目流程

程序内部用的字符串,用Ordinal;展示给人看的文字,用CurrentCulture。

记住这句话,90% 的场景就不会选错。下面解释为什么。

一、为什么字符串比较有好几种?

因为"两个字符串谁排前面"有两种完全不同的标准:

  • 计算机的标准:每个字符都有一个编号,按编号大小比。
  • 人的标准:像查字典一样,按字母顺序比。

这两种标准经常给出相反的结果。StringComparer就是让你选择用哪种标准。

二、Ordinal:按编号比

每个字符在计算机里都有一个编号:

数字 0~9 = 48~57 大写 A~Z = 65~90 小写 a~z = 97~122 é = 233

Ordinal 只看编号大小,从左往右逐个比,遇到第一个不同的字符就定胜负。

所以它的排序是:数字 → 大写字母 → 小写字母 → 带重音的字母。

例子:"a"vs"B"

  • a 的编号是 97,B 的编号是 66
  • 97 更大,所以"a"排在后面

三、InvariantCulture:像查英文字典

它分三轮比较,前一轮分出胜负,就不再往下比:

  1. 第 1 轮:只看字母(忽略大小写和重音)
  2. 第 2 轮:看重音(没有重音的在前)
  3. 第 3 轮:看大小写(小写在前)

例子:

比较结果原因
"a"vs"B"a 在前第 1 轮:字典里 a 在 b 前面
"resume"vs"résumé"resume 在前第 1 轮打平,第 2 轮:没重音的在前
"apple"vs"Apple"apple 在前前两轮打平,第 3 轮:小写在前

四、同一对单词,两种规则结果相反

"apple"vs"Zebra":

规则怎么比谁在前
Ordinala=97,Z=90,Z 编号更小Zebra
InvariantCulture字典里 a 在 z 前面apple

对一组单词排序,差别更明显:

Ordinal: Apple, Zebra, apple, banana InvariantCulture: apple, Apple, banana, Zebra

第二种才是人觉得"正常"的顺序。

五、既然 InvariantCulture 更像人,为什么程序里推荐 Ordinal?

因为 InvariantCulture 有三个缺点:

  1. 慢。它要做三轮比较,Ordinal 只比数字。
  2. 会"看不见"某些字符。比如软连字符这种不可见字符会被直接忽略,"coop"和中间藏了一个不可见字符的"co­op"会被判断为相等。如果用它做安全校验,可能被人绕过。
  3. 结果可能因系统而异。它依赖操作系统的语言库,不同版本可能有细微差别。

而程序内部的字符串(字典的键、文件名、配置项、网址)根本不需要"像人一样"排序,只需要快、准、永远不变。这正是 Ordinal 的优点。

六、Culture 是什么?

Culture(区域性)就是**“某个国家或地区的书写习惯”**,比如zh-CN(中国大陆中文)、en-US(美国英语)、de-DE(德国德语)。

它不只影响字符串比较,还影响很多东西:

影响什么美国 en-US德国 de-DE
数字1,234.561.234,56
货币$1,234.561.234,56 €
日期10/13/202613.10.2026

一个常见的坑:在德国电脑上,double.Parse("1.5")得到的是15,而不是 1.5,因为德国人用点号作千位分隔符。

三种 Culture 的区别:

  • CurrentCulture:跟着用户电脑的设置走。中国用户看到中国格式,德国用户看到德国格式。
  • InvariantCulture:固定不变的"通用格式"(基于英语),在任何电脑上都一样。适合保存文件、写配置。
  • 具体某个 Culture:比如new CultureInfo("de-DE"),你指定用哪国规则就用哪国。

七、OrdinalIgnoreCase 是怎么忽略大小写的?

简单理解:把字母都转成大写,再按编号比。

所以"Hello"和"HELLO"相等。

需要知道的两个细节:

  1. 它一个字符对一个字符地转换。德语的ß不会变成SS,所以"Straße"和"STRASSE"不相等。
  2. 它不受用户电脑设置影响。在土耳其语环境下,i的大写是İ(带点),如果用CurrentCultureIgnoreCase,"file"和"FILE"会被判断为不相等。而OrdinalIgnoreCase永远判断为相等。

所以不要写a.ToUpper() == b.ToUpper(),直接用OrdinalIgnoreCase,更快也更安全。

八、怎么选?一张表搞定

场景用哪个
字典的键、标识符、Linux 文件名Ordinal
HTTP 头、Windows 文件名、环境变量OrdinalIgnoreCase
给用户看的列表排序CurrentCulture
给用户用的搜索框CurrentCultureIgnoreCase
需要按字典排序,但要求每台电脑结果一样InvariantCulture
把数字、日期保存到文件或 JSONCultureInfo.InvariantCulture(用于格式化)

九、动手试试

新建控制台项目,把下面代码粘贴到Program.cs,运行dotnet run:

usingSystem.Globalization;string[]words={"banana","Apple","apple","Zebra"};// 1. 两种规则排序对比Console.WriteLine("Ordinal: "+string.Join(", ",words.OrderBy(w=>w,StringComparer.Ordinal)));Console.WriteLine("InvariantCulture: "+string.Join(", ",words.OrderBy(w=>w,StringComparer.InvariantCulture)));// 2. 忽略大小写的字典vardict=newDictionary<string,int>(StringComparer.OrdinalIgnoreCase){["Name"]=1};Console.WriteLine("找到 name 吗?"+dict.ContainsKey("name"));// True// 3. 土耳其语陷阱CultureInfo.CurrentCulture=newCultureInfo("tr-TR");Console.WriteLine("CurrentCultureIgnoreCase: "+StringComparer.CurrentCultureIgnoreCase.Equals("file","FILE"));// FalseConsole.WriteLine("OrdinalIgnoreCase: "+StringComparer.OrdinalIgnoreCase.Equals("file","FILE"));// True// 4. 德国格式解析陷阱Console.WriteLine("德国解析 1.5 = "+double.Parse("1.5",newCultureInfo("de-DE")));// 15

总结

  • Ordinal= 按编号比,快、准、永远不变,适合程序内部。
  • InvariantCulture= 按字典比(字母 → 重音 → 大小写),适合需要固定结果的人类可读排序。
  • CurrentCulture= 按用户所在地区的习惯比,适合展示给用户。
  • Culture不只管比较,还管数字、货币、日期的格式。
  • OrdinalIgnoreCase= 转大写后按编号比,忽略大小写时的首选。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询