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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44288/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 09:54:37  来源:igfitidea点击:

Differences in string compare methods in C#

提问by Craig

Comparing string in C# is pretty simple. In fact there are several ways to do it. I have listed some in the block below. What I am curious about are the differences between them and when one should be used over the others? Should one be avoided at all costs? Are there more I haven't listed?

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

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

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

(Note: I am looking for equality in this example, not less than or greater than but feel free to comment on that as well)

(注意:我在这个例子中寻找相等,不小于或大于但也可以对此发表评论)

采纳答案by Lasse V. Karlsen

Here are the rules for how these functions work:

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

stringValue.CompareTo(otherStringValue)

stringValue.CompareTo(otherStringValue)

  1. nullcomes before a string
  2. it uses CultureInfo.CurrentCulture.CompareInfo.Compare, which means it will use a culture-dependent comparison. This might mean that ?will compare equal to SSin Germany, or similar
  1. null出现在字符串之前
  2. 它使用CultureInfo.CurrentCulture.CompareInfo.Compare,这意味着它将使用依赖于文化的比较。这可能意味着?将与SS德国或类似

stringValue.Equals(otherStringValue)

stringValue.Equals(otherStringValue)

  1. nullis not considered equal to anything
  2. unless you specify a StringComparisonoption, it will use what looks like a direct ordinal equality check, i.e. ?is not the same as SS, in any language or culture
  1. null不被认为等于任何东西
  2. 除非你指定一个StringComparison选项,它会用什么样子的直接序平等的检查,即?是不一样的SS,在任何语言或文化

stringValue == otherStringValue

stringValue == otherStringValue

  1. Is not the same as stringValue.Equals().
  2. The ==operator calls the static Equals(string a, string b)method (which in turn goes to an internal EqualsHelperto do the comparison.
  3. Calling .Equals()on a nullstring gets nullreference exception, while on ==does not.
  1. 不一样stringValue.Equals()
  2. ==运营商调用静态Equals(string a, string b)方法(这反过来又转到内部EqualsHelper做比较。
  3. 调用.Equals()一个null字符串被null引用异常,同时==没有。

Object.ReferenceEquals(stringValue, otherStringValue)

Object.ReferenceEquals(stringValue, otherStringValue)

Just checks that references are the same, i.e. it isn't just two strings with the same contents, you're comparing a string object with itself.

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



Note that with the options above that use method calls, there are overloads with more options to specify how to compare.

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

My advice if you just want to check for equality is to make up your mind whether you want to use a culture-dependent comparison or not, and then use .CompareToor .Equals, depending on the choice.

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

回答by Ed S.

From MSDN:

来自 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."

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

They suggest using .Equalsinstead of .CompareTowhen looking solely for equality. I am not sure if there is a difference between .Equalsand ==for the stringclass. I will sometimes use .Equalsor Object.ReferenceEqualsinstead of ==for my own classes in case someone comes along at a later time and redefines the ==operator for that class.

他们建议在仅寻求平等时使用.Equals而不是.CompareTo。我不知道是否有之间的差异.Equals,并==string类。我有时会使用.EqualsorObject.ReferenceEquals代替==我自己的类,以防有人稍后出现并重新定义==该类的运算符。

回答by OwenP

In the forms you listed here, there's not much difference between the two. CompareToends up calling a CompareInfomethod that does a comparison using the current culture; Equalsis called by the ==operator.

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

If you consider overloads, then things get different. Compareand ==can only use the current culture to compare a string. Equalsand String.Comparecan take a StringComparisonenumeration argument that let you specify culture-insensitive or case-insensitive comparisons. Only String.Compareallows you to specify a CultureInfoand perform comparisons using a culture other than the default culture.

如果你考虑重载,那么事情就会变得不同。 Compare并且==只能使用当前区域性来比较字符串。 Equals并且String.Compare可以采用StringComparison枚举参数,让您指定不区分区域性或不区分大小写的比较。仅String.Compare允许您指定 aCultureInfo并使用默认区域性以外的区域性执行比较。

Because of its versatility, I find I use String.Comparemore than any other comparison method; it lets me specify exactly what I want.

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

回答by hometoast

Using .Equals is also a lot easier to read.

使用 .Equals 也更容易阅读

回答by viggity

Not that performance usually matters with 99% of the times you need to do this, but if you had to do this in a loop several million times I would highly suggest that you use .Equals or == because as soon as it finds a character that doesn't match it throws the whole thing out as false, but if you use the CompareTo it will have to figure out which character is less than the other, leading to slightly worse performance time.

99% 的情况下,性能通常并不重要,您需要这样做,但是如果您必须在循环中执行数百万次,我强烈建议您使用 .Equals 或 ==,因为一旦找到一个字符不匹配它会将整个事情抛出为false,但是如果您使用CompareTo,它将必须确定哪个字符小于另一个字符,从而导致性能时间稍差。

If your app will be running in different countries, I'd recommend that you take a look at the CultureInfo implications and possibly use .Equals. Since I only really write apps for the US (and don't care if it doesn't work properly by someone), I always just use ==.

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

回答by max

If you are ever curious about differences in BCL methods, Reflectoris your friend :-)

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

I follow these guidelines:

我遵循以下准则:

Exact match:EDIT: I previously always used == operator on the principle that inside Equals(string, string) the object == operator is used to compare the object references but it seems strA.Equals(strB) is still 1-11% faster overall than string.Equals(strA, strB), strA == strB, and string.CompareOrdinal(strA, strB). I loop tested with a StopWatch on both interned/non-interned string values, with same/different string lengths, and varying sizes (1B to 5MB).

完全匹配:编辑:我以前总是使用 == 运算符,其原理是在 Equals(string, string) 内部使用对象 == 运算符来比较对象引用,但似乎 strA.Equals(strB) 仍然是 1-11%总体上比 string.Equals(strA, strB)、strA == strB 和 string.CompareOrdinal(strA, strB) 快。我使用 StopWatch 对具有相同/不同字符串长度和不同大小(1B 到 5MB)的内部/非内部字符串值进行了循环测试。

strA.Equals(strB)

Human-readable match (Western cultures, case-insensitive):

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

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

Human-readable match (All other cultures, insensitive case/accent/kana/etc defined by CultureInfo):

人类可读的匹配(所有其他文化,由 CultureInfo 定义的不区分大小写/重音/假名/等):

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

Human-readable match with custom rules (All other cultures):

与自定义规则的人类可读匹配(所有其他文化):

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

回答by Jonathan C Dickinson

As Edsaid, CompareTo is used for sorting.

正如Ed所说,CompareTo 用于排序。

There is a difference, however, between .Equals and ==.

但是,.Equals 和 == 之间是有区别的。

== resolves to essentiallythe following code:

==基本上解析为以下代码:

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

The simple reason is the following will throw an exception:

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

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

bool equal = a.Equals(b);

And the following will not:

而以下不会:

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

bool equal = a == b;

回答by David

with .Equals, you also gain the StringComparison options. very handy for ignoring case and other things.

使用 .Equals,您还可以获得 StringComparison 选项。忽略大小写和其他事情非常方便。

btw, this will evaluate to false

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

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

return a==b

Since == compares the values of a and b (which are pointers) this will only evaluate to true if the pointers point to the same object in memory. .Equals dereferences the pointers and compares the values stored at the pointers. a.Equals(b) would be true here.

由于 == 比较 a 和 b (它们是指针)的值,因此只有当指针指向内存中的同一对象时,才会评估为真。.Equals 取消对指针的引用并比较存储在指针中的值。a.Equals(b) 在这里为真。

and if you change b to:

如果您将 b 更改为:

b = "MYSTRING";

then a.Equals(b) is false, but

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

a.Equals(b, StringComparison.OrdinalIgnoreCase) 

would be true

会是真的

a.CompareTo(b) calls the string's CompareTo function which compares the values at the pointers and returns <0 if the value stored at a is less than the value stored at b, returns 0 if a.Equals(b) is true, and >0 otherwise. However, this is case sensitive, I think there are possibly options for CompareTo to ignore case and such, but don't have time to look now. As others have already stated, this would be done for sorting. Comparing for equality in this manner would result in unecessary overhead.

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

I'm sure I'm leaving stuff out, but I think this should be enough info to start experimenting if you need more details.

我确定我会遗漏一些东西,但我认为如果您需要更多详细信息,这应该足以开始试验。

回答by Ryszard D?egan

Good explanation and practices about string comparison issues may be found in the article New Recommendations for Using Strings in Microsoft .NET 2.0and also in Best Practices for Using Strings in the .NET Framework.

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



Each of mentioned method (and other) has particular purpose. The key difference between them is what sort of StringComparison Enumerationthey are using by default. There are several options:

提到的每种方法(和其他方法)都有特定的用途。它们之间的主要区别在于它们默认使用的StringComparison 枚举类型。有几种选择:

  • CurrentCulture
  • CurrentCultureIgnoreCase
  • InvariantCulture
  • InvariantCultureIgnoreCase
  • Ordinal
  • OrdinalIgnoreCase
  • 当前文化
  • CurrentCultureIgnoreCase
  • 不变文化
  • InvariantCultureIgnoreCase
  • 序数
  • 顺序忽略大小写

Each of above comparison type targets different use case:

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

  • Ordinal
    • Case-sensitive internal identifiers
    • Case-sensitive identifiers in standards like XML and HTTP
    • Case-sensitive security-related settings
  • OrdinalIgnoreCase
    • Case-insensitive internal identifiers
    • Case-insensitive identifiers in standards like XML and HTTP
    • File paths (on Microsoft Windows)
    • Registry keys/values
    • Environment variables
    • Resource identifiers (handle names, for example)
    • Case insensitive security related settings
  • InvariantCulture or InvariantCultureIgnoreCase
    • Some persisted linguistically-relevant data
    • Display of linguistic data requiring a fixed sort order
  • CurrentCulture or CurrentCultureIgnoreCase
    • Data displayed to the user
    • Most user input
  • 序数
    • 区分大小写的内部标识符
    • XML 和 HTTP 等标准中区分大小写的标识符
    • 区分大小写的安全相关设置
  • 顺序忽略大小写
    • 不区分大小写的内部标识符
    • XML 和 HTTP 等标准中不区分大小写的标识符
    • 文件路径(在 Microsoft Windows 上)
    • 注册表项/值
    • 环境变量
    • 资源标识符(例如句柄名称)
    • 不区分大小写的安全相关设置
  • InvariantCulture 或 InvariantCultureIgnoreCase
    • 一些持久的语言相关数据
    • 显示需要固定排序顺序的语言数据
  • CurrentCulture 或 CurrentCultureIgnoreCase
    • 显示给用户的数据
    • 大多数用户输入

Note, that StringComparison Enumerationas well as overloads for string comparison methods, exists since .NET 2.0.

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



String.CompareTo Method (String)

String.CompareTo 方法(字符串)

Is in fact type safe implementation of IComparable.CompareTo Method. Default interpretation: CurrentCulture.

实际上是IComparable.CompareTo Method 的类型安全实现。默认解释:CurrentCulture。

Usage:

用法:

The CompareTo method was designed primarily for use in sorting or alphabetizing operations

CompareTo 方法主要设计用于排序或字母排序操作

Thus

因此

Implementing the IComparable interface will necessarily use this method

实现 IComparable 接口必然会用到这个方法

String.Compare Method

String.Compare 方法

A static member of String Classwhich has many overloads. Default interpretation: CurrentCulture.

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

Whenever possible, you should call an overload of the Compare method that includes a StringComparison parameter.

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

String.Equals Method

String.Equals 方法

Overriden from Object class and overloaded for type safety. Default interpretation: Ordinal. Notice that:

从 Object 类重写并重载以确保类型安全。默认解释:序数。请注意:

The String class's equality methods include the static Equals, the static operator ==, and the instance method Equals.

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



StringComparer class

StringComparer 类

There is also another way to deal with string comparisons especially aims to sorting:

还有另一种处理字符串比较的方法,特别是针对排序:

You can use the StringComparer classto create a type-specific comparison to sort the elements in a generic collection. Classes such as Hashtable, Dictionary, SortedList, and SortedList use the StringComparer class for sorting purposes.

您可以使用StringComparer 类创建特定于类型的比较,以对泛型集合中的元素进行排序。Hashtable、Dictionary、SortedList 和 SortedList 等类使用 StringComparer 类进行排序。

回答by Rauld

One BIG difference to note is .Equals() will throw an exception if first string is null, Whereas == will not.

需要注意的一个大区别是 .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");