22

有多种方法可以比较字符串。以一种方式胜过另一种方式是否会提高性能?

我一直选择像这样比较字符串:

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 查询中进行这样的字符串比较。

4

10 回答 10

28

根据反射器

"Hello" == "World"

是相同的

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

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

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

是相同的

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

就功能而言,这基本上是相反的。它考虑了文化、编码以及与字符串相关的所有其他内容。

所以我想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 用于标准数组内容,那么我上面列出的规则适用。

于 2009-05-13T17:45:50.407 回答
16

在我看来,您应该始终使用最清晰的方法,即使用==!

这可以直接理解为:当“Hello”等于“World”时再做点什么。

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

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

这里不是很清楚——为什么要与零比较?

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

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

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

Linq 在这里的行为与常规 C# 没有什么不同。

于 2009-05-13T16:48:24.697 回答
8

阅读 Jeff 的The Best Code is No Code at Allfoo.CompareTo(bar) == 0: 可怕的视觉混乱。占用大量空间,并没有传达有趣的含义。事实上,它强调了许多无关紧要的东西,从而将注意力从真正的问题上转移开。

如果没有明确的理由使用这个更长的变体,不要。

至于性能:对于这个简单的案例来说根本不重要。如果相等运算符的==性能确实比 差CompareTo,请随时向 Microsoft 提交错误报告。这决不能发生。

于 2009-05-13T16:50:10.683 回答
5

那么 MSDN 声明您应该根据需要执行的任务使用比较功能:

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

因此,如果它不是关于排序并且重新运行值不重要,我会说应该使用:

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

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

看看这些链接:

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

String.CompareTo 方法(对象)

于 2013-01-14T06:55:01.867 回答
2

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

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

于 2009-05-13T16:41:23.897 回答
1

有一篇不错的文章Comparing Values for Equality in .NET:Identity and Equivalence,它比单纯的字符串比较更通用,但非常有趣。

于 2009-05-13T16:58:09.033 回答
1

如果相等运算符的实际性能比CompareTo- 微软不会实现相等运算符调用CompareTo吗?

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

于 2009-05-13T17:19:19.373 回答
1

是我找到的关于字符串比较的最完整和最有用的 MSDN 指南。

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

于 2014-07-23T06:35:00.793 回答
0

我通常将 String.Compare 与采用 StringComparison 参数的重载一起使用,因为这样我就可以绝对明确地确定比较是否区分大小写和区域性。这需要 .NET 2.0 或更高版本。

对于不区分区域性的比较,最快的是 StringComparison.Ordinal(或 StringComparison.OrdinalIgnoreCase,如果不区分大小写)。

使用 == 的问题在于,作者是否考虑了大小写和文化敏感性尚不清楚。

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

于 2009-05-13T17:28:46.190 回答
-1

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

如果要使用==符号,如果两个对象具有相同的引用,则结果将相等,但是当它们具有不同的引用并具有相同的值时,您将遇到问题。

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

于 2009-05-13T17:47:55.097 回答