在C#中比较两个字符串,忽略大小写

450

以下两种方案哪个更有效率?(或者也许有第三个选项更好?)

string val = "AStringValue";

if (val.Equals("astringvalue", StringComparison.InvariantCultureIgnoreCase))
OR
if (val.ToLowerCase() == "astringvalue")

?


15
我认为这是一个错误的问题。正确的问题应该是“哪一个更正确?” - asawyer
2
还有以下代码:if (string.Compare(strA, strB, StringComparison.OrdinalIgnoreCase) == 0) 或者 if (val.Equals("AStringValue", StringComparison.OrdinalIgnoreCase)),正确性往往也取决于个人偏好,在 https://dev59.com/3nVD5IYBdhLWcg3wO5AD 上有更多关于哪种方法是正确的讨论。 - Mark
5
@asawyer,为什么说“more correct”比“more efficient”更正确? - foxy
1
Jon Skeet已经在这里回答了这个问题(https://dev59.com/9HA65IYBdhLWcg3wrQh4)。 - Øyvind Bråthen
我更喜欢Equals,因为它像Ronsell一样(它能够做到它所说的)在一行中完成。而ToLowercase需要阅读上面的行,并结合它们的逻辑来确定为什么要将任何内容转换为小写。 - TinyRacoon
8个回答

421

如果你想要更高的效率,请使用这个方法:

string.Equals(val, "astringvalue", StringComparison.OrdinalIgnoreCase)

序数比较可以比区分文化的比较更快。

但是,如果您对同一字符串进行大量比较,ToLowerCase 可能是更好的选择。

与任何性能优化一样: 先测量,再决定!


13
调用静态方法时,我通常会使用类名,比如String.Equals(大写的'S')或者Int32.Parse而不是int.Parse。对于OrdinalIgnoreCase的提示很有帮助。谢谢。 - orad
1
@FrederikGheysels 我猜Sven建议你将ToLower()的结果存储在一个变量中,然后对每个比较进行操作。 - pwdst
@pwdst:这意味着您还需要对要与存储的变量进行比较的每个其他字符串执行 tolower。 - Frederik Gheysels
4
@FrederikGheysels 正确,但是StringComparer.OrdinalIgnoreCase的文档说明“由OrdinalIgnoreCase属性返回的StringComparer将比较字符串中的字符视为使用不变文化的约定转换为大写字母,然后执行独立于语言的简单字节比较。”(请参见 https://msdn.microsoft.com/zh-cn/library/system.stringcomparer.ordinalignorecase.aspx)。如果可以存储左侧比较的结果,则只需要在右侧进行处理。 - pwdst
1
@orad,您能解释一下为什么这样更好吗? - ErroneousFatality
显示剩余4条评论

217

第一个是正确的,也是在我看来更加有效的,因为第二种“解决方案”实例化了一个新的字符串实例。


15
除了效率之外,我更多地看到第二种解决方案的使用,因为它有效、缩短了代码长度并且更易于键入,并且具有易于记忆和直观的格式。“StringComparison.InvariantCultureIgnoreCase”…真的吗? - BengalTigger
1
@BengalTigger 至少第二个示例应该使用 ToLowerInvariant()。但是,第一个示例可能会实例化两个新的字符串实例,因此不一定更快。 - jpaugh

51

.ToLowerCase的版本不会更快 - 它涉及到额外的字符串分配(必须稍后收集),等等。

个人而言,我会使用

string.Equals(val, "astringvalue",  StringComparison.OrdinalIgnoreCase)
这样做可以避免与特定语言文化相关的字符串问题,但作为后果它也避免了所有与此相关的问题。只有您知道在您的情况下是否可以接受这种影响。
使用string.Equals静态方法可以避免val为空时的任何问题。

3
为什么您使用 StringComparison.OrdinalIgnoreCase 而不是 StringComparison.InvariantCultureIgnoreCase? - mqpasta
3
@mqpasta - 当然,这取决于目的,但http://msdn.microsoft.com/en-us/library/system.stringcomparer.ordinalignorecase.aspx“这在比较以编程方式生成的字符串或比较不区分大小写的资源(如路径和文件名)时最合适。” - 此外,它稍微快一点。 - Marc Gravell
@mqpasta:OrdinalIgnoreCase 比 InvariantCultureIgnoreCase 更高效。 - Tim Schmelter

14

对于关于“效率”的这类问题,我的一般回答几乎总是:哪个版本的代码最易读,哪个版本就最有效率。

话虽如此,我认为(val.ToLowerCase() == "astringvalue")对于绝大多数人来说一眼就能理解。

我所指的效率不一定在于代码的执行,而更多地在于代码的维护和整体可读性。


1
在编程中,使用EqualsStringComparison.OrdinalIgnoreCase一起使用既易读又更少出错,特别是对于像上面示例中的字符串字面量。您甚至可以创建一个扩展方法EqualsIgnoreCase,它内部决定使用哪个StringComparison - Lukas Körfer

9
我敢说最安全的做法是使用静态方法String.Equals,以减少在值为null的情况下出现NullReferenceException的可能性。

6

前者速度最快。原来val是不可变的,所以使用String.ToLowerCase()创建了一个新的字符串对象,而不是直接使用字符串比较器进行比较。如果每秒钟这样做多次,创建新的字符串对象可能会很昂贵。


3

2

第一种方法更高效(也是最佳选项),因为val.ToLowerCase()会创建一个新的对象,因为字符串是不可变的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接