首页 文章

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

提问于
浏览
242

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

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

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

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

11 回答

  • 16

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

    stringValue.CompareTo(otherStringValue)

    • null 出现在字符串之前

    • 它使用 CultureInfo.CurrentCulture.CompareInfo.Compare ,这意味着它将使用依赖于文化的比较 . 这可能意味着 ß 将与德国的 SS 相比,或类似

    stringValue.Equals(otherStringValue)

    • null 被认为不等于任何东西

    • 除非您指定 StringComparison 选项,否则它将使用看起来像直接序数相等检查的内容,即 ßSS 不同,在任何语言或文化中

    stringValue == otherStringValue

    • stringValue.Equals() 不同 .

    • == 运算符调用静态 Equals(string a, string b) 方法(后者又转到内部 EqualsHelper 进行比较 .

    • null 字符串上调用 .Equals() 得到 null 引用异常,而 == 则没有 .

    Object.ReferenceEquals(stringValue, otherStringValue)

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


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

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

  • 13

    来自MSDN:

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

    他们建议在仅仅考虑相等性时使用 .Equals 而不是 .CompareTo . 我不确定 .Equals== 之间是否存在 .Equals== 之间的区别 . 我有时会为自己的类使用 .EqualsObject.ReferenceEquals 而不是 == ,以防有人稍后出现并重新定义该类的 == 运算符 .

  • 213

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

    我遵循以下准则:

    Exact match: 编辑:我之前总是使用==运算符,原理是在Equals(字符串,字符串)内,对象==运算符用于比较对象引用,但看起来strA.Equals(strB)的整体速度仍然快1-11%比string.Equals(strA,strB),strA == strB和string.CompareOrdinal(strA,strB) . 我在Interned / non-interned字符串值上使用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):

    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
    
  • 49

    正如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;
    
  • -1

    有关字符串比较问题的详细解释和做法可以在文章New Recommendations for Using Strings in Microsoft .NET 2.0Best Practices for Using Strings in the .NET Framework中找到 .


    所提到的每种方法(和其他)都有特定的目的 . 它们之间的关键区别在于它们默认使用的是哪种StringComparison Enumeration . 有几种选择:

    • CurrentCulture

    • CurrentCultureIgnoreCase

    • InvariantCulture

    • InvariantCultureIgnoreCase

    • 序数

    • OrdinalIgnoreCase

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

    • 序数

    • 区分大小写的内部标识符

    • XML和HTTP等标准中的区分大小写的标识符

    • 区分大小写的安全相关设置

    • OrdinalIgnoreCase

    • 不区分大小写的内部标识符

    • XML和HTTP等标准中不区分大小写的标识符

    • 文件路径(在Microsoft Windows上)

    • 注册表项/值

    • 环境变量

    • 资源标识符(例如,句柄名称)

    • 不区分大小写安全相关设置

    • InvariantCulture或InvariantCultureIgnoreCase

    • 一些持久的语言相关数据

    • 显示需要固定排序顺序的语言数据

    • CurrentCulture或CurrentCultureIgnoreCase

    • 向用户显示数据

    • 大多数用户输入

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


    String.CompareTo方法(String)

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

    用法:

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

    从而

    实现IComparable接口必然会使用此方法

    String.Compare方法

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

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

    String.Equals方法

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

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


    StringComparer类

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

    您可以使用StringComparer类创建特定于类型的比较,以对通用集合中的元素进行排序 . 诸如Hashtable,Dictionary,SortedList和SortedList之类的类使用StringComparer类进行排序 .

  • 5

    并非性能通常在99%的时间内都很重要,但是如果你必须循环数百万次,我强烈建议您使用.Equals或==因为一旦找到一个字符与它不匹配的东西将整个东西抛出为假,但是如果你使用CompareTo它将必须弄清楚哪个字符小于另一个,导致稍差的性能时间 .

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

  • 70

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

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

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

  • -9

    需要注意的一个重要区别是,如果第一个字符串为null,则.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");
    
  • 7
    • s1.CompareTo(s2): 如果主要目的是确定两个字符串是否相同,请不要使用

    • s1 == s2: 不能忽视大小写

    • s1.Equals(s2, StringComparison): 如果s1为null,则抛出NullReferenceException

    • String.Equals(s2, StringComparison): 通过消除过程,这个静态方法是 WINNER (假设一个典型的用例来确定两个字符串是否相等)!

  • 0

    使用.Equals也更容易阅读 .

  • 2

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

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

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

    由于==比较a和b(它们是指针)的值,如果指针指向内存中的同一对象,则只会求值为true . .Equals取消引用指针并比较存储在指针中的值 . a.Equals(b)在这里是真的 .

    如果你将b改为:

    b = "MYSTRING";
    

    然后a.Equals(b)是假的,但是

    a.Equals(b, StringComparison.OrdinalIgnoreCase)
    

    是真的

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

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

相关问题