c#中字符串比较方法的差异

在c#中比较字符串是非常简单的。事实上有几种方法可以做到这一点。我在下面列出了一些。我好奇的是它们之间的区别,以及什么时候应该使用其中一种?是否应该不惜一切代价避免?还有其他我没有列出的吗?

string testString = "Test";
string anotherString = "Another";


if (testString.CompareTo(anotherString) == 0) {}
if (testString.Equals(anotherString)) {}
if (testString == anotherString) {}

(注:我在这个例子中寻找平等,不小于或大于,但也可以自由评论)

203310 次浏览

从MSDN:

CompareTo方法主要是设计用于排序或 排序操作。它不应该用于初级 该方法调用的目的是确定两个字符串是否正确 等价的。要确定两个字符串是否等效,请调用 Equals方法。" < / p >

他们建议在仅寻找相等时使用.Equals而不是.CompareTo。我不确定string类的.Equals==之间是否有区别。我有时会在我自己的类中使用.EqualsObject.ReferenceEquals而不是==,以防稍后有人出现并为该类重新定义==操作符。

在你列出的表格中,两者之间没有太大的区别。CompareTo最终调用CompareInfo方法,该方法使用当前区域性进行比较;Equals==操作符调用。

如果考虑到过载,情况就不一样了。Compare==只能使用当前区域性来比较字符串。EqualsString.Compare可以接受一个StringComparison枚举参数,用于指定区域性不敏感或大小写不敏感的比较。只有String.Compare允许你指定CultureInfo并使用默认区域性以外的区域性执行比较。

由于它的多功能性,我发现我使用String.Compare比任何其他比较方法都多;它可以让我精确地指定我想要的东西。

使用. equals也更容易

不是性能通常有99%的时间你需要这样做,但是如果你不得不这样做在一个循环中数百万倍。我强烈建议你使用.Equals或= =因为当它发现一个字符不匹配它把整个事情是假的,但是如果你使用CompareTo就必须找出哪些字符小于另一个,从而导致稍差的性能。

如果您的应用程序将在不同的国家运行,我建议您查看CultureInfo的含义,并可能使用. equals。因为我只为美国编写应用程序(并不关心它是否由某人正常工作),我总是使用==。

下面是这些函数的工作规则:

stringValue.CompareTo(otherStringValue)

  1. null出现在字符串之前
  2. 它使用CultureInfo.CurrentCulture.CompareInfo.Compare,这意味着它将使用依赖于区域性的比较。这可能意味着ß将比较等于德国的SS,或类似

stringValue.Equals(otherStringValue)

  1. null不被认为等于任何东西
  2. 除非你指定了StringComparison选项,否则它将使用类似于直接序号相等性检查的方法,即在任何语言或文化中,ßSS是不同的

stringValue == otherStringValue

  1. stringValue.Equals()不相同。
  2. ==操作符调用静态Equals(string a, string b)方法(该方法又转到内部EqualsHelper进行比较。
  3. null字符串上调用.Equals()会得到null引用异常,而在==上则不会。

Object.ReferenceEquals(stringValue, otherStringValue)

只是检查引用是否相同,即它不只是两个具有相同内容的字符串,你是在比较字符串对象和它本身。


注意,对于上面使用方法调用的选项,有更多的重载选项来指定如何进行比较。

如果你只是想检查是否相等,我的建议是决定是否要使用依赖于文化的比较,然后根据选择使用.CompareTo.Equals

如果你对BCL方法的差异感到好奇,反射器是你的朋友:-)

我遵循以下准则:

精确匹配: 编辑:我以前总是使用==操作符的原则是,在Equals(string, string)中,对象==操作符用于比较对象引用,但似乎str .Equals(strB)总体上仍然比string快1-11%。= (strA, strB), strA == strB,和string。CompareOrdinal(箍,strB)。我用一个秒表对被拘禁/非被拘禁的字符串值进行循环测试,具有相同/不同的字符串长度,以及不同的大小(1B到5MB)。

strA.Equals(strB)

人类可读匹配(西方文化,不区分大小写):

string.Compare(strA, strB, StringComparison.OrdinalIgnoreCase) == 0

人类可读匹配(CultureInfo定义的所有其他区域性,不敏感的大小写/重音/假名/等):

string.Compare(strA, strB, myCultureInfo) == 0

人类可读的自定义规则匹配(所有其他区域性):

CompareOptions compareOptions = CompareOptions.IgnoreCase
| CompareOptions.IgnoreWidth
| CompareOptions.IgnoreNonSpace;
string.Compare(strA, strB, CultureInfo.CurrentCulture, compareOptions) == 0

正如艾德所说,CompareTo用于排序。

然而,. equals和==之间是有区别的。

==将以下代码解析为本质上:

if(object.ReferenceEquals(left, null) &&
object.ReferenceEquals(right, null))
return true;
if(object.ReferenceEquals(left, null))
return right.Equals(left);
return left.Equals(right);

原因很简单,下面的代码会抛出异常:

string a = null;
string b = "foo";


bool equal = a.Equals(b);

而下面这些则不会:

string a = null;
string b = "foo";


bool equal = a == b;

使用. equals,你还可以获得StringComparison选项。对于忽略大小写和其他东西非常方便。

顺便说一句,这将计算为假

string a = "myString";
string b = "myString";


return a==b
因为==比较a和b的值(它们都是指针),只有当指针指向内存中的同一个对象时,这才会计算为true . equals解引用指针并比较指针上存储的值。 a.等于(b)在这里为真。

如果把b改成:

b = "MYSTRING";

那么a = (b)是假的,但是

a.Equals(b, StringComparison.OrdinalIgnoreCase)

是正确的

a.CompareTo(b)调用字符串的CompareTo函数,该函数比较指针上的值,如果存储在a处的值小于存储在b处的值,则返回<0,如果a. equals (b)为真,则返回0,否则返回>0。然而,这是区分大小写的,我认为CompareTo可能有忽略大小写等选项,但现在没有时间看。 正如其他人已经指出的,这将用于排序。以这种方式进行相等比较将导致不必要的开销

我确定我遗漏了一些东西,但我认为如果你需要更多细节,这些信息应该足够开始试验了。

关于字符串比较问题的良好解释和实践可以在文章关于在Microsoft .NET 2.0中使用字符串的新建议在.NET框架中使用字符串的最佳实践中找到。


上述每一种方法(或其他方法)都有特定的目的。它们之间的关键区别是默认使用的接受StringComparison枚举类型。有以下几种选择:

  • CurrentCulture
  • CurrentCultureIgnoreCase
  • InvariantCulture
  • InvariantCultureIgnoreCase
  • 序数
  • OrdinalIgnoreCase

以上每一种比较类型都针对不同的用例:

需要注意的一个重大区别是. equals()将在第一个字符串为空时抛出异常,而==则不会。

       string s = null;
string a = "a";
//Throws {"Object reference not set to an instance of an object."}
if (s.Equals(a))
Console.WriteLine("s is equal to a");
//no Exception
if(s==a)
Console.WriteLine("s is equal to a");
  • s1.CompareTo (s2):如果主要目的是确定两个字符串是否等效,请不要使用
  • S1 == s2:不能忽略大小写
  • s1。接受StringComparison Equals (s2):如果s1为空则抛出NullReferenceException
  • 通过消除过程,这个静态方法是赢家(假设一个典型的用例来确定两个字符串是否等效)!