背景
想想c#对==
的重写,平时写代码时遇到字符串的比较直接使用==,但回头看这么写容易引起误会,为了能够更好的编写出好看的代码,这里先系统的举出c#中常见的比较方法。
1.Equals()
在对字符串比较中==与Equals()的普通用法相同(详细内容可见之前写的c#中Equals()与==的比较),Equals()的作用与优化比我们想象的要好的的多,话不多说,先上代码,然后再谈谈细节。
string s1 = "Hello";
string s2 = "Hello";
string s3 = "hello";
string res = string.Empty;
res += "s1.Equals(s2):" + s1.Equals(s2);
res += "\n s1.Equals(s3):" + s1.Equals(s3);
res += "\n string.Equals(s1, s2);" + string.Equals(s1, s2);
res += "\n string.Equals(s1, s3);" + string.Equals(s1, s3);
res += "\n string.Equals(s1, s2, StringComparison.Ordinal);" + string.Equals(s1, s2, StringComparison.Ordinal);
res += "\n string.Equals(s1, s3, StringComparison.Ordinal);" + string.Equals(s1, s3, StringComparison.Ordinal);
res += "\n s1.Equals(s3, StringComparison.OrdinalIgnoreCase):" + s1.Equals(s3, StringComparison.OrdinalIgnoreCase);
res += "\n s1.Equals(s2, StringComparison.OrdinalIgnoreCase):" + s1.Equals(s2, StringComparison.OrdinalIgnoreCase);
res += "\n string.Equals(s1, s3, StringComparison.OrdinalIgnoreCase);" + string.Equals(s1, s3, StringComparison.OrdinalIgnoreCase);
其运行结果为:
这里格式为:s1.Equals(s2)
与string.Equals(s1, s2)
,格式相同、效果相同,这时我就在想既然两个效果都是一样的,那为什么要分两种写法。别急,其实看到上面举的例子就可以看到两者的不同。
首先是范围,s1.Equals(s2)
他的范围是Object对象,而string.Equals(s1, s2)
则专注于字符串的比较。其次看效果,就单单是对string字符串的比较string.Equals(s1, s2)
的效果更好,也是推荐使用的;这是为何?第一:当需要比较忽略大小写的字符串时,通常会想到的是先将字符串ToLower()或者ToUpper(),然后再来比较,这么写大体看是没错,但是有几点不足之处,一是多写了代码(一句话能解决的为什么要多写几行),二是效率低下,三是逻辑要严谨(这里需要添加判断字符串是否为空)。c#为了方便我这样的菜鸟提供了StringComparison的重写Equals()方法,当我们正常比较时用StringComparison.Ordinal
,例如string.Equals(s1, s2, StringComparison.Ordinal)
,当比较忽略大小写时用StringComparison.OrdinalIgnoreCase
,例如s1.Equals(s2, StringComparison.OrdinalIgnoreCase)
,使用StringComparison可以减少代码量,并且可以提高性能,至于StringComparison的一些介绍我将他放到最后面讲。
2.CompareTo()
CompareTo()
返回值不是布尔值,而是int整数值,并且返回的也不是ASCII值,他返回-1、0、1三个整数值,举例如下:
string s1 = "Hello";
string s2 = "Hello";
string s3 = "hello";
res += "s1.CompareTo(s2):" + s1.CompareTo(s2);
res += "\n s1.CompareTo(s3):" + s1.CompareTo(s3);
其运行结果如图所示:
从上面运行结果可以看出,当格式为s1.CompareTo(s2)
,当s1与s2相等返回的是0,当s1的ASCII大于s2的ASCII时,返回1,当s1的ASCII小于s2的ASCII时,返回-1。
3.Compare()与CompareOrdinal()
Compare()与CompareOrdinal()都属于静态方法,速度要比上面的CompareTo()要快。接下来举例看看他们的效果:
string s1 = "Hello";
string s2 = "Hello";
string s3 = "hello";
res += "\n string.Compare(s1, s2);" + string.Compare(s1, s2);
res += "\n string.Compare(s1, s3);" + string.Compare(s1, s3);
res += "\n string.Compare(s1, s3, true);" + string.Compare(s1, s3, true);
res += "\nstring.Compare(s1, s3, StringComparison.Ordinal);" + string.Compare(s1, s3, StringComparison.Ordinal);
res += "\n string.Compare(s1, s3, StringComparison.OrdinalIgnoreCase);" + string.Compare(s1, s3, StringComparison.OrdinalIgnoreCase);
res += "\n string.CompareOrdinal(s1, s2);" + string.CompareOrdinal(s1, s2);
res += "\n string.CompareOrdinal(s1, s3);" + string.CompareOrdinal(s1, s3);
其运行结果如图所示:
鼠标往Compare()一放显示他有九个重载,这里暂不详细讲解着九个重载的用处,只举出通常使用的例子。首先Compare()与CompareTo()相近,返回的就-1、0、1三个整数值,例如:string.Compare(s1, s2)
中s1 > s2 : 1、s1 = s2 : 0、s1 < s2:-1,正常使用的时候还有一个是Compare(String strA, String strB, bool ignoreCase)
,默认情况是false,如果想要忽略大小写比较就需要将ignoreCase设置为true。
而CompareOrdinal(s1, s2)
与Compare(s1, s2, StringComparison.Ordinal)
的效果相同,返回的是ASCII值,这其中的区别我想就是CompareOrdinal()比Compare()少写了StringComparison.Ordinal,性能方面CompareOrdinal()比Compare()好点。当然如果想要忽略大小写更改为Compare(s1, s2, StringComparison.OrdinalIgnoreCase)
补充讲解StringComparison
String.Compare(string1,string2,StringComparison.Ordinal)的时候是进行非语言(non-linguistic)上的比较,API运行时将会对两个字符串进行byte级别的比较,因此这种比较是比较严格和准确的,并且在性能上也很好,一般通过StringComparison.Ordinal来进行比较比使用String.Compare(string1,string2)来比较要快。StringComparison.OrdinalIgnoreCase就是忽略大小写的比较,同样是byte级别的比较.性能稍弱于StringComparison.Ordinal
StringComparison.CurrentCulture
、StringComparison.InvariantCulture
是根据区域信息来比较,如果不涉及国际业务是用不到这两个的,详细情况可以参考博客:StringComparison