在C#中比较字符串非常简单.事实上,有几种方法可以做到这一点.我在下面的块中列出了一些.我很好奇的是它们之间的差异以及何时应该使用其他的?是否应该不惜一切代价避免?还有更多我没有列出?
string testString = "Test"; string anotherString = "Another"; if (testString.CompareTo(anotherString) == 0) {} if (testString.Equals(anotherString)) {} if (testString == anotherString) {}
(注意:我在这个例子中寻找平等,不小于或大于,但也可以随意发表评论)
以下是这些功能如何工作的规则:
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
做比较.
调用.Equals()
一个null
字符串被null
引用异常,同时==
没有.
Object.ReferenceEquals(stringValue, otherStringValue)
只检查引用是否相同,即它不只是具有相同内容的两个字符串,而是将字符串对象与自身进行比较.
请注意,使用上面使用方法调用的选项,有一些重载,有更多选项来指定如何比较.
如果你只是想检查是否平等,我的建议就是决定是否要使用依赖于文化的比较,然后使用.CompareTo
或.Equals
取决于选择.
来自MSDN:
"CompareTo方法主要用于排序或字母顺序操作.当方法调用的主要目的是确定两个字符串是否相同时,不应使用它.要确定两个字符串是否相等,请调用Equals方法. "
他们建议使用.Equals
而不是.CompareTo
仅仅寻求平等.我不知道是否有之间的差异.Equals
,并==
为string
类.我有时会使用.Equals
或Object.ReferenceEquals
代替==
我自己的类,以防有人稍后出现并重新定义==
该类的运算符.
如果您对BCL方法的差异感到好奇,Reflector就是您的朋友:-)
我遵循以下准则:
完全匹配: 编辑:我以前总是使用==运算符,原理是在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)
人类可读的匹配(西方文化,不区分大小写):
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;
有关字符串比较问题的详细解释和实践可以在Microsoft .NET 2.0中使用字符串的新建议文章以及.NET Framework中使用字符串的最佳实践中找到.
所提到的每种方法(和其他)都有特定的目的.它们之间的主要区别在于它们默认使用的是哪种StringComparison枚举.有几种选择:
的CurrentCulture
CurrentCultureIgnoreCase
InvariantCulture的
InvariantCultureIgnoreCase
序数词
OrdinalIgnoreCase
以上每种比较类型都针对不同的用例:
序数词
区分大小写的内部标识符
XML和HTTP等标准中的区分大小写的标识符
区分大小写的安全相关设置
OrdinalIgnoreCase
不区分大小写的内部标识符
XML和HTTP等标准中的不区分大小写的标识符
文件路径(在Microsoft Windows上)
注册表项/值
环境变量
资源标识符(例如,句柄名称)
不区分大小写的安全相关设置
InvariantCulture或InvariantCultureIgnoreCase
一些持久的语言相关数据
显示需要固定排序顺序的语言数据
CurrentCulture或CurrentCultureIgnoreCase
显示给用户的数据
大多数用户输入
请注意,自.NET 2.0以来,存在StringComparison枚举以及字符串比较方法的重载.
实际上是IComparable.CompareTo方法的类型安全实现.默认解释:CurrentCulture.
用法:
CompareTo方法主要用于排序或字母顺序操作
从而
实现IComparable接口必然会使用此方法
String Class的静态成员,具有许多重载.默认解释:CurrentCulture.
只要有可能,您应该调用包含StringComparison参数的Compare方法的重载.
从Object类重写并重载以确保类型安全.默认解释:序数.请注意:
String类的相等方法包括静态Equals,静态运算符==和实例方法Equals.
还有另一种处理字符串比较的方法,特别是旨在排序:
您可以使用StringComparer类创建特定于类型的比较,以对通用集合中的元素进行排序.诸如Hashtable,Dictionary,SortedList和SortedList之类的类使用StringComparer类进行排序.
并非性能通常在99%的时间内都很重要,但是如果你必须循环数百万次,我强烈建议您使用.Equals或==因为一旦找到一个字符与它不匹配的东西将整个东西抛出为假,但是如果你使用CompareTo它将必须弄清楚哪个字符小于另一个,导致稍差的性能时间.
如果您的应用程序将在不同的国家/地区运行,我建议您查看CultureInfo含义并可能使用.Equals.因为我只为美国编写应用程序(并且不关心某人是否无法正常工作),所以我总是只使用==.
在这里列出的表格中,两者之间没有太大区别. CompareTo
最终调用一个CompareInfo
使用当前文化进行比较的方法; Equals
由==
运营商召集.
如果你考虑过载,那么情况会有所不同. Compare
并且==
只能使用当前文化来比较字符串. Equals
并且String.Compare
可以使用StringComparison
枚举参数,该参数允许您指定对文化不敏感或不区分大小写的比较.仅String.Compare
允许您CultureInfo
使用默认区域性以外的区域性来指定和执行比较.
由于它的多功能性,我发现我使用的String.Compare
比任何其他比较方法更多; 它让我准确指出我想要的东西.