您的位置:首页 > 编程语言 > C#

C#中字符串的比较操作

2017-06-13 15:45 501 查看


C#中字符串的比较操作

http://www.cnblogs.com/junbird-nest/archive/2012/03/23/2413557.html


字符串比较是比较常用的操作,一般出于以下两个原因比较字符串:

判断相等
字符串排序
查询API判断字符串相等或排序时,由以下方法:
 
public override bool Equals(object obj);
public bool Equals(string value);
public static bool Equals(string a, string b);
public bool Equals(string value, StringComparison comparisonType);
public static bool Equals(string a, string b, StringComparison comparisonType);

public static int Compare(string strA, string strB);
public static int Compare(string strA, string strB, bool ignoreCase);
public static int Compare(string strA, string strB, StringComparison comparisonType);
public static int Compare(string strA, string strB, bool ignoreCase, CultureInfo culture);
public static int Compare(string strA, string strB, CultureInfo culture, CompareOptions options);
public static int Compare(string strA, int indexA, string strB, int indexB, int length);
public static int Compare(string strA, int indexA, string strB, int indexB, int length, bool ignoreCase);
public static int Compare(string strA, int indexA, string strB, int indexB, int length, StringComparison comparisonType);
public static int Compare(string strA, int indexA, string strB, int indexB, int length, bool ignoreCase, CultureInfo culture);
public static int Compare(string strA, int indexA, string strB, int indexB, int length, CultureInfo culture, CompareOptions options);

public static int CompareOrdinal(string strA, string strB);
public static int CompareOrdinal(string strA, int indexA, string strB, int indexB, int length);

public int CompareTo(object value);
public int CompareTo(string strB);

发现上述的方法中大多都有StringComparison类型的枚举,查询msdn后得到:



现简单写一段代码,测试Compare(string strA, string strB, StringComparison comparisonType)方法。分别用到StringComparison.CurrentCulture
和StringComparison.Ordinal。代码如下:
static void Main(string[] args)
{
string strA = "asdfadsfasdfew我ò啊?地?方?的?asd";
string strB = "adsfeaqfaead啊?多à发¢安2德?森-efadsfa";
Stopwatch sw = new Stopwatch();

sw.Start();
for (int i = 0; i < 1000000; i++)
{
string.Compare(strA, strB, StringComparison.CurrentCulture);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);

sw.Reset();
for (int i = 0; i < 1000000; i++)
{
string.Compare(strA, strB,StringComparison.Ordinal);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);

sw.Reset();
for (int i = 0; i < 1000000; i++)
{
string.CompareOrdinal(strA, strB);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}

执行结果如下:



测试结果非常明显,StringComparison.Currentculture显式传递了当前语言文化,而传递了String.Ordinal则会忽略指定的语言文化,这是执行字符串最快的一种方式。
使用.NET Reflector查看源代码:
public static int Compare(string strA, string strB, StringComparison comparisonType)
{
if ((comparisonType < StringComparison.CurrentCulture) || (comparisonType > StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
}
if (strA == strB)
{
return 0;
}
if (strA == null)
{
return -1;
}
if (strB == null)
{
return 1;
}
switch (comparisonType)
{
case StringComparison.CurrentCulture:
return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.None);

case StringComparison.CurrentCultureIgnoreCase:
return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.IgnoreCase);

case StringComparison.InvariantCulture:
return CultureInfo.InvariantCulture.CompareInfo.Compare(strA, strB, CompareOptions.None);

case StringComparison.InvariantCultureIgnoreCase:
return CultureInfo.InvariantCulture.CompareInfo.Compare(strA, strB, CompareOptions.IgnoreCase);

case StringComparison.Ordinal:
return CompareOrdinalHelper(strA, strB);

case StringComparison.OrdinalIgnoreCase:
if (!strA.IsAscii() || !strB.IsAscii())
{
return TextInfo.CompareOrdinalIgnoreCase(strA, strB);
}
return CompareOrdinalIgnoreCaseHelper(strA, strB);
}
throw new NotSupportedException(Environment.GetResourceString("NotSupported_StringComparison"));
}

在上例中,同时测试了String的CompareOrdinal方法,效率同样惊人。查看其源代码后发现与Compare方法String.Ordinal源代码一样,此方法只是Compare方法的一个特例:

 

public static int CompareOrdinal(string strA, string strB)
{
if (strA == strB)
{
return 0;
}
if (strA == null)
{
return -1;
}
if (strB == null)
{
return 1;
}
return CompareOrdinalHelper(strA, strB);
}

 
 
接下来看看String.CompareTo()方法的源代码:
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
public int CompareTo(string strB)
{
if (strB == null)
{
return 1;
}
return CultureInfo.CurrentCulture.CompareInfo.Compare(this, strB, CompareOptions.None);
}

与类型参数为StringComparison.CurrentCulture的Compare方法相同。
 
 
另外StringComparer也实现了字符串比较方法Compare()方法。直接看源代码:
public int Compare(object x, object y)
{
if (x == y)
{
return 0;
}
if (x == null)
{
return -1;
}
if (y == null)
{
return 1;
}
string str = x as string;
if (str != null)
{
string str2 = y as string;
if (str2 != null)
{
return this.Compare(str, str2);
}
}
IComparable comparable = x as IComparable;
if (comparable == null)
{
throw new ArgumentException(Environment.GetResourceString("Argument_ImplementIComparable"));
}
return comparable.CompareTo(y);
}

 
 
如果程序只将字符串用于内部编码目的,如路径名、文件名、URL、环境变量、反射、XML标记等,这些字符串通常只在程序内部使用,不会像用户展示,应该使用String.Ordinal或者使用String.CompareOrdinal()方法
 
总结及建议:
使用显示地指定了字符串比较规则的重载函数。一般来说,需要带有StringComparison类型参数的重载函数
在对未知文化的字符串做比较时,使用StringComparison.Ordinal和StringComparison.OrdinallgnoreCase作为默认值,提高性能
在像用户输出结果时,使用基于StringComparison.CurrentCulture的字符串
使用String.Equals的重载版本来测试两个字符串是否相等。
不要使用String.Compare或CompareTo的重载版本来检测返回值是否为0来判断字符串是否相等。这两个函数是用于字符串比较,而非检查相等性。
在字符串比较时,应以String.ToUpperInvariant函数使字符串规范化,而不用ToLowerInvariant方法,因为Microsoft对执行大写比较的代码进行了优化。之所以不用ToUpper和ToLower方法,是因为其对语言文化敏感。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: