C#中string比较方法的区别

在C#中比较string非常简单。 实际上有几种方法可以做到这一点。 我在下面的部分列出了一些。 我很好奇他们之间的区别,什么时候应该使用其他的? 应该不惜一切代价避免? 还有更多我没有列出?

string testString = "Test"; string anotherString = "Another"; if (testString.CompareTo(anotherString) == 0) {} if (testString.Equals(anotherString)) {} if (testString == anotherString) {} 

(注意:我在这个例子中寻找的是平等的,不是小于或者大于,但也可以随意评论)

以下是这些function如何工作的规则:

stringValue.CompareTo(otherStringValue):

  1. null在string之前
  2. 它使用CultureInfo.CurrentCulture.CompareInfo.Compare,这意味着它将使用文化相关的比较。 这可能意味着ß将与德国的SS相当,或类似

stringValue.Equals(otherStringValue):

  1. null不被视为等于任何东西
  2. 除非你指定一个StringComparison选项,否则它将使用看起来像一个直接的序数相等性检查,即。 在任何语言或文化中,SS都不一样

stringValue == otherStringValue:

  1. 与stringValue.Equals()不一样。
  2. ==运算符调用静态Equals(stringa,stringb)方法(进而转到内部EqualsHelper进行比较。
  3. 对空string调用.Equals()会得到空引用exception,而on ==不会。

Object.ReferenceEquals(stringValue,otherStringValue):

只要检查参考是相同的,即。 它不仅仅是两个内容相同的string,而是将一个string对象与自己进行比较。


请注意,使用上述使用方法调用的选项,有重载和更多的选项来指定如何比较。

我的build议,如果你只是想检查平等是让你想想要使用文化依赖的比较或不,然后使用.CompareTo或.Equals,根据select。

来自MSDN:

“CompareTo方法主要用于sorting或字母sorting操作,当方法调用的主要目的是确定两个string是否相等时,不应使用CompareTo方法。要确定两个string是否相等,请调用Equals方法。 “

他们build议使用.Equals而不是.CompareTo当只是为了平等。 我不确定string类是否有.Equals==之间的区别。 我有时候会使用.EqualsObject.ReferenceEquals而不是==为我自己的类,以防某些人稍后出现并重新定义该类的==运算符。

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

我遵循这些准则:

完全匹配: 编辑:我以前总是使用==运算符的原则,内部等于(string,string)对象==运算符用于比较对象引用,但它似乎strA.Equals(strB)仍然是1-11%整体比string.Equals(strA,strB),strA == strB和string.CompareOrdinal(strA,strB)更快。 我使用StopWatch对interned / non-internedstring值进行循环testing,具有相同/不同的string长度以及不同的大小(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 

正如Ed所说,CompareTo用于sorting。

.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); 

简单的原因是下面会抛出一个exception:

 string a = null; string b = "foo"; bool equal = a.Equals(b); 

以下不会:

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

关于string比较问题的好的解释和实践可以在文章“在Microsoft .NET 2.0中使用string的新build议”以及“ 在.NET Framework中使用string的最佳实践”中find 。


提到的每一种方法(和其他)都有特定的目的。 它们之间的主要区别在于它们默认使用了什么types的StringComparison枚举 。 有几个选项:

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

以上每个比较types的目标不同的用例:

  • 序数词
    • 区分大小写的内部标识符
    • 标准中的区分大小写的标识符,如XML和HTTP
    • 区分大小写的安全相关设置
  • OrdinalIgnoreCase
    • 不区分大小写的内部标识符
    • XML和HTTP等标准中不区分大小写的标识符
    • 文件path(在Microsoft Windows上)
    • registry项/值
    • 环境variables
    • 资源标识符(例如句柄名称)
    • 不区分大小写的安全相关设置
  • InvariantCulture或InvariantCultureIgnoreCase
    • 一些坚持语言相关的数据
    • 显示需要固定sorting顺序的语言数据
  • CurrentCulture或CurrentCultureIgnoreCase
    • 数据显示给用户
    • 大多数用户input

请注意, StringComparison枚举以及string比较方法的重载,自.NET 2.0以来就存在。


String.CompareTo方法(string)

其实是IComparable.CompareTo方法的types安全实现。 默认解释:CurrentCulture。

用法:

CompareTo方法主要用于sorting或字母sorting操作

从而

实现IComparable接口将必然使用这种方法

String.Compare方法

一个String类的静态成员,有许多重载。 默认解释:CurrentCulture。

只要有可能,就应该调用包含StringComparison参数的Compare方法的重载。

String.Equals方法

从Object类中覆盖并重载以保证types安全。 默认解释:序数。 请注意:

String类的相等方法包括静态Equals静态运算符==实例方法Equals


StringComparer类

还有另一种处理string比较的方法,特别是针对sorting:

您可以使用StringComparer类创build特定types的比较,以对generics集合中的元素进行sorting。 类如Hashtable,Dictionary,SortedList和SortedList使用StringComparer类进行sorting。

并不是说性能通常与99%的时间需要这么做有关系,但是如果你必须在循环中做数百万次,我会强烈build议你使用.Equals或==,因为只要它find一个字符不匹配它会把整个事件抛出为false,但是如果使用CompareTo,则必须找出哪个字符小于另一个字符,导致稍微差一点的性能时间。

如果你的应用程序将运行在不同的国家,我build议你看一下CultureInfo的含义,并可能使用.Equals。 由于我只是真的写美国的应用程序(并不关心,如果它不能正常工作),我总是使用==。

在这里列出的表格中,两者没有太大的区别。 CompareTo最终调用一个CompareInfo方法,使用当前的文化进行比较; Equals==运算符调用。

如果你考虑过重,那么事情就会变得不同。 Compare==只能使用当前的文化来比较一个string。 EqualsString.Compare可以使用一个StringComparison枚举参数,让您指定不区分大小写或不区分大小写的比较。 只有String.Compare允许你指定一个CultureInfo并使用非默认文化进行比较。

由于其通用性,我发现我比其他任何比较方法都使用了String.Compare 。 它让我指定我想要的。

一个重要的区别是.Equals()会抛出一个exception,如果第一个string为空,Whereas ==不会。

  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"); 

使用.Equals也更容易阅读

CompareTo将string与string对象进行比较,并返回一个int值。 如果该值为0,则表示string相等。

 string country = "southindia"; object ob1 = country.Clone(); Console.WriteLine( country.CompareTo(ob1)); string country = "southindia"; string cou = "insia"; int n = country.CompareTo(cou); Console.WriteLine( n ); 

与.Equals,你也获得StringComparison选项。 非常方便无视案件和其他事情。

顺便说一句,这将评估为假

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

由于==比较了a和b(它们是指针)的值,只有当指针指向内存中的同一个对象时,才会计算为真。 .Equals解引用指针并比较存储在指针处的值。 a.Equals(b)在这里将是真实的。

如果您将b更改为:

 b = "MYSTRING"; 

那么a.Equals(b)是错误的,但是

 a.Equals(b, StringComparison.OrdinalIgnoreCase) 

将是真实的

a.CompareTo(b)调用string的CompareTo函数,该函数比较指针处的值,如果a处存储的值小于b处存储的值,则返回<0;如果a.Equals(b)为true,则返回0;否则为0。 但是,这是区分大小写的,我认为可能有CompareTo的选项来忽略大小写,但是现在没有时间去查看。 正如其他人已经指出,这将做分拣。 以这种方式比较平等会导致不必要的开销。

我敢肯定,我会把东西丢掉,但是我认为这应该是足够的信息来开始试验,如果你需要更多的细节。