首选 string.equals(str1, str2, stringcomparison.ordinalignorecase),因其跨平台一致、不依赖文化、无临时字符串分配且性能最优;禁用 tolower/toupper 和默认重载,集合键比较须用 stringcomparer.ordinalignorecase 构造。

直接用 String.Equals(str1, str2, StringComparison.OrdinalIgnoreCase),这是最安全、最高效、跨平台一致的忽略大小写比较方式。别用 .ToLower() 或 .ToUpper(),也别依赖默认重载或 string.Compare(a, b, true) 这种模糊调用。
为什么 StringComparison.OrdinalIgnoreCase 是首选
它不依赖当前线程的 CultureInfo,在 Windows、Linux、macOS 上行为完全一致;底层基于 Unicode 码点做固定映射(比如 'A'→'a' 的转换规则是硬编码的),不触发文化敏感逻辑;没有临时字符串分配,GC 压力小。
常见错误场景:
-
"İ".ToLower()在土耳其语文化下不是"i",会导致匹配失败 -
str1 == str2或string.Equals(str1, str2)默认走StringComparison.Ordinal,严格区分大小写 -
string.Compare(a, b, true)的true参数实际调用的是CurrentCultureIgnoreCase,行为随系统区域设置漂移
StringComparer.OrdinalIgnoreCase 用于集合键比较
当你把字符串当字典 key、哈希集元素或排序列表项时,光靠 Equals 不够——必须把比较器传进构造函数,否则 "Content-Type" 和 "content-type" 就是两个不同 key。
正确写法:
var headers = new Dictionary<string string>(StringComparer.OrdinalIgnoreCase); headers["Accept"] = "application/json"; Console.WriteLine(headers["accept"]); // 输出 application/json</string>
注意点:
-
StringComparer.OrdinalIgnoreCase是静态只读实例,可全局复用,不要每次new StringComparer - 别混用
StringComparer.CurrentCultureIgnoreCase:部署到不同语言系统的服务器上可能出错 - 这个比较器只影响“相等性判断”,不能用于排序(如
SortedList要求严格全序,需额外处理)
string.Compare 忽略大小写的正确调用姿势
string.Compare 返回整数(负/零/正),适合需要判断字典序先后的场景,但必须显式指定 StringComparison 枚举值,不能只传布尔。
错误写法:string.Compare(a, b, true) —— 这会走文化敏感比较,且参数含义模糊
正确写法:
- 相等判断:
string.Compare(str1, str2, StringComparison.OrdinalIgnoreCase) == 0 - 排序用途:
list.Sort((x, y) => string.Compare(x, y, StringComparison.OrdinalIgnoreCase)) - 子串比较:
string.Compare(str1, 0, str2, 0, Math.Min(str1.Length, str2.Length), StringComparison.OrdinalIgnoreCase)
性能提示:如果只是判断是否相等,String.Equals 比 string.Compare(...)==0 略快,因为前者可短路优化。
哪些地方绝对不能用 OrdinalIgnoreCase
它只解决“是否相等”问题,不适用于需要文化感知的场景:
- 用户界面显示的排序(比如通讯录按姓氏排序,中文、德语、阿拉伯语规则不同)
- 文件名规范化(Windows 不区分大小写,Linux 区分,但
OrdinalIgnoreCase无法替代 OS 层语义) - 正则表达式匹配 —— 那里要用
RegexOptions.IgnoreCase,和字符串比较器无关 -
StartsWith、Contains等方法有对应重载,如str.StartsWith("abc", StringComparison.OrdinalIgnoreCase),别自己手动截取再比
最容易被忽略的一点:很多人以为设了 StringComparer.OrdinalIgnoreCase 就万事大吉,但忘了它对 Dictionary 的 key 是“一次性生效”的——一旦 key 插入,后续修改原始字符串内容不会自动更新哈希值,这跟引用类型的行为有关,得自己心里有数。











