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

时间:2020-03-05 18:47:46  来源:igfitidea点击:

在Cis中比较字符串非常简单。实际上,有几种方法可以做到这一点。我在下面的方框中列出了一些。我很好奇的是它们之间的区别以及何时应该使用它们之间的区别?应该不惜一切代价避免一个吗?我还没有列出更多吗?

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

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

(注意:我在此示例中寻求的是平等,不小于或者大于但也可以对此发表评论)

解决方案

回答

从MSDN:

"The CompareTo method was designed primarily for use in sorting or
  alphabetizing      operations. It should not be used when the primary
  purpose of the method call is to     determine whether two strings are
  equivalent. To determine whether two strings are    equivalent, call
  the Equals method."

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

回答

在此处列出的表单中,两者之间没有太大区别。 " CompareTo"最终调用" CompareInfo"方法,该方法使用当前区域性进行比较。 "等于"由" =="运算符调用。

如果考虑过载,情况会有所不同。 "比较"和" =="只能使用当前区域性来比较字符串。 " Equals"和" String.Compare"可以采用" StringComparison"枚举参数,该参数可让我们指定不区分文化或者不区分大小写的比较。只有String.Compare允许我们指定CultureInfo并使用默认区域性以外的区域性进行比较。

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

回答

使用.Equals也更容易阅读。

回答

并不是说性能通常不会影响我们需要执行此操作的99%的时间,但是如果我们必须循环执行几百万次,我强烈建议我们使用.Equals或者==,因为一旦找到字符如果不匹配,则会将整个结果视为错误,但是如果使用CompareTo,则必须找出哪个字符比另一个字符少,从而导致性能时间稍差。

如果应用程序将在不同的国家/地区运行,建议我们查看一下CultureInfo的含义,并可能使用.Equals。由于我只为美国真正编写应用程序(并且不在乎是否有人无法正常工作),因此我始终只使用==。

回答

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

stringValue.CompareTo(otherStringValue)

  • null在字符串之前
  • 它使用CultureInfo.CurrentCulture.CompareInfo.Compare,这意味着它将使用与文化相关的比较。这可能意味着等于德国的SS或者类似值。

stringValue.Equals(otherStringValue)

  • null被认为不等于任何东西
  • 除非我们指定StringComparison选项,否则它将使用看起来像直接有序相等性检查的东西,即在任何语言或者文化中,SS都不相同。

stringValue == otherStringValue

  • stringValue.Equals()不同。
  • " =="运算符调用静态的" Equals(字符串a,字符串b)"方法(该方法又转到内部的" EqualsHelper"中进行比较)。
  • null字符串上调用.Equals()会得到null引用异常,而在==上则不会。

Object.ReferenceEquals(stringValue,otherStringValue)

只需检查引用是否相同,即不仅仅是两个具有相同内容的字符串,而是将一个字符串对象与其自身进行比较。

请注意,使用上述使用方法调用的选项时,会出现重载,其中包含更多选项来指定如何进行比较。

如果我们只想检查是否相等,我的建议是决定是否要使用与文化相关的比较,然后根据选择使用.CompareTo或者.Equals

回答

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

我遵循以下准则:

完全匹配:编辑:我以前总是使用==运算符,其原理是在Equals(string,string)内使用object ==运算符来比较对象引用,但看起来strA.Equals(strB)仍为1-11%总体上比string.Equals(strA,strB),strA == strB和string.CompareOrdinal(strA,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

回答

正如Ed所说,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选项。对于忽略大小写和其他内容非常方便。

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

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

return a==b

因为==比较a和b的值(它们是指针),所以只有当指针指向内存中的同一对象时,这才算为true。 .Equals取消引用指针,并比较存储在指针处的值。
a。等于(b)在这里是正确的。

并且如果将b更改为:

b = "MYSTRING";

那么a.Equals(b)为假,但是

a.Equals(b, StringComparison.OrdinalIgnoreCase)

会是真的

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

我确定我会遗漏任何东西,但是如果我们需要更多详细信息,我认为这应该足够开始尝试的信息。