C#中的字符串比较性能

有许多方法可以比较字符串。 通过单一方式获得性能提升吗?

我总是选择像这样比较字符串:

string name = "Bob Wazowski"; if (name.CompareTo("Jill Yearsley") == 0) { // whatever... } 

但我发现很少有人这样做,如果有的话,我看到更多的人只是做一个直接的==比较,据我所知,这是比较字符串的最差方式。 我错了吗?

另外,它是如何比较LINQ查询中的字符串的? 例如,我喜欢做以下事情:

 var results = from names in ctx.Names where names.FirstName.CompareTo("Bob Wazowski") == 0 select names; 

但同样,我看到很少有人在他们的LINQ查询中进行字符串比较。

根据Reflector

 "Hello" == "World" 

是相同的

 String.Equals("Hello", "World"); 

它基本上确定它们是否是同一个引用对象,如果它们中的任何一个为null,如果一个为null而另一个为null则为自动false,然后比较不安全循环中的每个字符。 因此它根本不关心文化规则,这通常不是什么大问题。

 "Hello".CompareTo("World") == 0 

是相同的

 CultureInfo.CurrentCulture.CompareInfo.Compare("Hello", "World", CompareOptions.None); 

就function而言,这基本上是相反的。 它将字符串输入到上下文中考虑了文化,编码和其他所有内容。

所以我想象String.CompareTo比相等运算符慢几个数量级

对于LINQ而言,如果使用LINQ-to-SQL并不重要,因为两者都会生成相同的SQL

 var results = from names in ctx.Names where names.FirstName.CompareTo("Bob Wazowski") == 0 select names; 

 SELECT [name fields] FROM [Names] AS [t0] WHERE [t0].FirstName = @p0 

所以你真的没有为LINQ-to-SQL获得任何东西,除了更难阅读代码和可能更多的表达式解析。 如果你只是使用LINQ作为标准数组的东西,那么我上面列出的规则就适用了。

在我看来,你应该总是使用最清晰的方式,即使用==

这可以直接理解:当“你好”等于“世界”然后做点什么。

 if ("Hello" == "World") // ... 

在内部,调用String::Equals ,为此目的明确存在 – 比较两个字符串是否相等。 (这与指针和引用等无关)

这里不是立即清楚 – 为什么比较为零?

 if ("Hello".CompareTo("World") == 0) 

.CompareTo不仅仅用于检查相等性(你有==) – 它比较两个字符串。 您可以使用.CompareTo来确定一个字符串比另一个字符串“更大”。 你可以检查是否相等,因为对于相等的字符串它会产生零,但这不是它的概念。

因此,有不同的方法和接口用于检查相等性(IEquatable,operator ==)和比较(IComparable)

Linq与常规C#的行为不同。

阅读杰夫的最佳代码完全没有代码foo.CompareTo(bar) == 0 :可怕的视觉混乱。 占用大量空间并没有传达任何有趣的意义。 事实上,它强调了许多无关紧要的东西,这些东西会将注意力从真正的问题上转移开。

如果使用这个较长的变体没有明确的原因,请不要。

至于性能:这对于这个简单的情况来说无关紧要。 如果相等运算符==应该比CompareTo表现更差,请随时向Microsoft提交错误报告。 这绝不可能发生。

MSDN声明你应该根据你需要执行的任务使用比较函数:

CompareTo方法主要用于排序或字母顺序操作。 当方法调用的主要目的是确定两个字符串是否相等时,不应该使用它。 要确定两个字符串是否相等,请调用Equals方法。

因此,如果它不是关于排序和retrun值不重要我会说应该使用:

first.Equals(second)或者如果比较是文化特定的,例如在德语等语言中:

String.Equals(first, second, StringComparison.CurrentCulture)

看看这些链接:

如何:比较字符串(C#编程指南)

String.CompareTo方法(对象)

最近关于修剪字符串的最快方法有一个非常类似的问题,但它基本上是对不同比较方法的基准测试。

你可以查看这篇文章的基准。

有一篇很好的文章比较.NET中的平等价值:身份和等价 ,这比仅仅进行字符串比较更为通用,但非常有趣。

如果相等运算符实际上比CompareTo表现更差 – 微软是否会使相等运算符的实现调用CompareTo

只需使用相等运算符来测试相等性。

我通常使用带有StringComparison参数的重载的String.Compare,因为那时我可以绝对明确比较是否区分大小写和文化敏感。 这需要.NET 2.0或更高版本。

对于非文化敏感的比较,最快的是StringComparison.Ordinal(或StringComparison.OrdinalIgnoreCase,如果不区分大小写)。

使用==的问题在于,作者已经考虑了案例和文化敏感性并不清楚。

这里有关于这个主题的MSDN文章很好。

要在C#中比较string的最佳方法是使用a.Equals(b) ,其中ab是字符串。 这是比较字符串的最佳方法,因为它比较了对象ab的值,并且不依赖于对象的引用。

如果您要使用==符号,如果两个对象具有相同的引用,则结果将相等,但如果它们具有不同的引用并且具有相同的值,则会出现问题。

如果您测试另一个字符串是否在另一个字符串的相同位置之前,之后或出现在另一个字符串的相同位置,其中它将分别返回负值,正值或零值,则compareTo方法是最佳使用方法。 如果参数为null它也将返回正值

这是我发现的最完整,最有帮助的MSDN指南,用于字符串比较。

使用与StringComparison.Ordinal或StringComparison.OrdinalIgnoreCase的比较可获得更好的性能。