在C#中比较字符串非常简单 . 事实上,有几种方法可以做到这一点 . 我在下面的块中列出了一些 . 我很好奇的是它们之间的差异以及何时应该使用其他的?是否应该不惜一切代价避免?还有更多我没有列出?
string testString = "Test";
string anotherString = "Another";
if (testString.CompareTo(anotherString) == 0) {}
if (testString.Equals(anotherString)) {}
if (testString == anotherString) {}
(注意:我在这个例子中寻找平等,不小于或大于,但也可以随意发表评论)
11 回答
以下是这些功能如何工作的规则:
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
,具体取决于选择 .来自MSDN:
他们建议在仅仅考虑相等性时使用
.Equals
而不是.CompareTo
. 我不确定.Equals
和==
之间是否存在.Equals
和==
之间的区别 . 我有时会为自己的类使用.Equals
或Object.ReferenceEquals
而不是==
,以防有人稍后出现并重新定义该类的==
运算符 .如果您对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) .
Human-readable match (Western cultures, case-insensitive):
Human-readable match (All other cultures, insensitive case/accent/kana/etc defined by CultureInfo):
Human-readable match with custom rules (All other cultures):
正如Ed所说,CompareTo用于排序 .
但是,.Equals和==之间存在差异 .
==解析为基本上以下代码:
简单的原因是以下将抛出异常:
以下不会:
有关字符串比较问题的详细解释和做法可以在文章New Recommendations for Using Strings in Microsoft .NET 2.0和Best 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 .
用法:
从而
String.Compare方法
String Class的静态成员,具有许多重载 . 默认解释:CurrentCulture .
String.Equals方法
从Object类重写并重载以确保类型安全 . 默认解释:序数 . 请注意:
StringComparer类
还有另一种处理字符串比较的方法,特别是旨在排序:
并非性能通常在99%的时间内都很重要,但是如果你必须循环数百万次,我强烈建议您使用.Equals或==因为一旦找到一个字符与它不匹配的东西将整个东西抛出为假,但是如果你使用CompareTo它将必须弄清楚哪个字符小于另一个,导致稍差的性能时间 .
如果您的应用程序将在不同的国家/地区运行,我建议您查看CultureInfo含义并可能使用.Equals . 因为我只为美国编写应用程序(并且不关心某人是否无法正常工作),所以我总是只使用== .
在这里列出的表格中,两者之间没有太大区别 .
CompareTo
最终调用CompareInfo
方法,使用当前文化进行比较;Equals
由==
运算符调用 .如果你考虑过载,那么情况会有所不同 .
Compare
和==
只能使用当前文化来比较字符串 .Equals
和String.Compare
可以使用StringComparison
枚举参数,该参数允许您指定区分不区分大小写或不区分大小写的比较 . 只有String.Compare
允许您指定CultureInfo
并使用默认区域性以外的区域性进行比较 .由于它的多功能性,我发现我使用
String.Compare
比任何其他比较方法更多;它让我准确指出我想要的东西 .需要注意的一个重要区别是,如果第一个字符串为null,则.Equals()将抛出异常,而= =则不会 .
s1.CompareTo(s2): 如果主要目的是确定两个字符串是否相同,请不要使用
s1 == s2: 不能忽视大小写
s1.Equals(s2, StringComparison): 如果s1为null,则抛出NullReferenceException
String.Equals(s2, StringComparison): 通过消除过程,这个静态方法是 WINNER (假设一个典型的用例来确定两个字符串是否相等)!
使用.Equals也更容易阅读 .
使用.Equals,您还可以获得StringComparison选项 . 忽略案件和其他事情非常方便 .
顺便说一句,这将评估为假
由于==比较a和b(它们是指针)的值,如果指针指向内存中的同一对象,则只会求值为true . .Equals取消引用指针并比较存储在指针中的值 . a.Equals(b)在这里是真的 .
如果你将b改为:
然后a.Equals(b)是假的,但是
是真的
a.CompareTo(b)调用字符串的CompareTo函数,该函数比较指针处的值,如果存储在a处的值小于存储在b处的值则返回<0,如果a.Equals(b)为真则返回0,并且>否则为0 . 但是,这是区分大小写的,我认为CompareTo有可能选择忽略大小写,但不是现在有时间看 . 正如其他人已经说过的那样,这将用于分类 . 以这种方式比较相等将导致不必要的开销 .
我确定我要把东西丢掉,但我认为如果你需要更多的细节,这应该是足够的信息来开始试验 .