String.Equals(str1, str2, StringComparison.OrdinalIgnoreCase) 是最推荐的忽略大小写比较方式,不创建新字符串、不依赖文化、性能好、语义清晰;应避免使用 ToLower()/ToUpper()、CultureIgnoreCase 及未指定 StringComparison 的 Contains/StartsWith/EndsWith。

String.Equals 用 StringComparison.OrdinalIgnoreCase 最直接
这是最推荐的忽略大小写比较方式,不创建新字符串、不依赖当前文化、性能好、语义清晰。它底层是做一次大小写不变形的序号比较(ordinal),比 ToLower() 快且稳定。
-
String.Equals(str1, str2, StringComparison.OrdinalIgnoreCase)是首选,尤其适合配置项、路径、协议名等不涉及本地化语义的场景 - 避免用
str1.Equals(str2, StringComparison.OrdinalIgnoreCase)(实例方法),因为str1可能为null,会抛出NullReferenceException - 不要混用
StringComparison.CurrentCultureIgnoreCase:它受线程当前区域设置影响,在土耳其语中"i".ToUpper()不等于"I",可能引发意外行为
Contains / StartsWith / EndsWith 必须显式传 StringComparison
这些方法默认区分大小写,而且没有无参重载——不传 StringComparison 就是按 Ordinal 区分大小写比较。很多人以为 "Hello".Contains("h") 会返回 true,实际是 false。
-
"Hello".Contains("h", StringComparison.OrdinalIgnoreCase)✅ -
"Hello".StartsWith("h", StringComparison.OrdinalIgnoreCase)✅ -
"Hello".EndsWith("O", StringComparison.OrdinalIgnoreCase)✅ - 错误写法:
"Hello".Contains("h")或"Hello".Contains("h", StringComparison.CurrentCulture)—— 后者仍区分大小写
别用 ToLower() / ToUpper() 做比较
看似简单,但会分配新字符串、触发 GC、在某些语言下结果不可靠(比如土耳其语的 i → İ),而且无法用于 LINQ to Entities(EF 查询会报错)。
- ❌
str1.ToLower() == str2.ToLower()—— 多次分配,慢,且ToLower()在不同 .NET 版本或文化下行为可能不一致 - ❌
str1.ToUpper() == str2.ToUpper()—— 同上,且对某些 Unicode 字符(如德语 ß)转换后长度变化,可能出错 - ✅ 替代方案:统一用
String.Equals(a, b, StringComparison.OrdinalIgnoreCase)或a.Equals(b, StringComparison.OrdinalIgnoreCase)(确保 a 非 null)
EF Core 查询里忽略大小写要靠数据库能力
在 EF Core 中,StringComparison 参数无法翻译成 SQL,所以 .Where(x => x.Name.Equals("admin", StringComparison.OrdinalIgnoreCase)) 会在内存中执行(即先全量查出再过滤),性能灾难。
- 正确做法是用
.Where(x => x.Name.ToLower() == "admin".ToLower())—— 大多数数据库支持LOWER()函数翻译 - 或者用
.Where(x => EF.Functions.Like(x.Name, "admin"))(SQL Server)或ILIKE(PostgreSQL) - 更安全的是在数据库建索引时用函数索引(如 PostgreSQL 的
CREATE INDEX ON users (LOWER(name)))
StringComparison.Ordinal 和 StringComparison.OrdinalIgnoreCase 是唯一保证跨平台、跨版本、跨文化行为一致的选项**。其他基于文化的比较,哪怕只在本地测试通过,上线后也可能因服务器区域设置不同而失败。


















