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

C#中字符串的比较操作

2012-03-23 13:55 363 查看

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

判断相等

字符串排序

查询API判断字符串相等或排序时,由以下方法:

publicoverrideboolEquals(objectobj);
publicboolEquals(stringvalue);
publicstaticboolEquals(stringa,stringb);
publicboolEquals(stringvalue,StringComparisoncomparisonType);
publicstaticboolEquals(stringa,stringb,StringComparisoncomparisonType);

publicstaticintCompare(stringstrA,stringstrB);
publicstaticintCompare(stringstrA,stringstrB,boolignoreCase);
publicstaticintCompare(stringstrA,stringstrB,StringComparisoncomparisonType);
publicstaticintCompare(stringstrA,stringstrB,boolignoreCase,CultureInfoculture);
publicstaticintCompare(stringstrA,stringstrB,CultureInfoculture,CompareOptionsoptions);
publicstaticintCompare(stringstrA,intindexA,stringstrB,intindexB,intlength);
publicstaticintCompare(stringstrA,intindexA,stringstrB,intindexB,intlength,boolignoreCase);
publicstaticintCompare(stringstrA,intindexA,stringstrB,intindexB,intlength,StringComparisoncomparisonType);
publicstaticintCompare(stringstrA,intindexA,stringstrB,intindexB,intlength,boolignoreCase,CultureInfoculture);
publicstaticintCompare(stringstrA,intindexA,stringstrB,intindexB,intlength,CultureInfoculture,CompareOptionsoptions);

publicstaticintCompareOrdinal(stringstrA,stringstrB);
publicstaticintCompareOrdinal(stringstrA,intindexA,stringstrB,intindexB,intlength);

publicintCompareTo(objectvalue);
publicintCompareTo(stringstrB);

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





现简单写一段代码,测试Compare(stringstrA,stringstrB,StringComparisoncomparisonType)方法。分别用到StringComparison.CurrentCulture和StringComparison.Ordinal。代码如下:

staticvoidMain(string[]args)
{
stringstrA="asdfadsfasdfew我ò啊?地?方?的?asd";
stringstrB="adsfeaqfaead啊?多à发¢安2德?森-efadsfa";
Stopwatchsw=newStopwatch();

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

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

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

执行结果如下:





测试结果非常明显,StringComparison.Currentculture显式传递了当前语言文化,而传递了String.Ordinal则会忽略指定的语言文化,这是执行字符串最快的一种方式。

使用.NETReflector查看源代码:

publicstaticintCompare(stringstrA,stringstrB,StringComparisoncomparisonType)
{
if((comparisonType<StringComparison.CurrentCulture)||(comparisonType>StringComparison.OrdinalIgnoreCase))
{
thrownewArgumentException(Environment.GetResourceString("NotSupported_StringComparison"),"comparisonType");
}
if(strA==strB)
{
return0;
}
if(strA==null)
{
return-1;
}
if(strB==null)
{
return1;
}
switch(comparisonType)
{
caseStringComparison.CurrentCulture:
returnCultureInfo.CurrentCulture.CompareInfo.Compare(strA,strB,CompareOptions.None);

caseStringComparison.CurrentCultureIgnoreCase:
returnCultureInfo.CurrentCulture.CompareInfo.Compare(strA,strB,CompareOptions.IgnoreCase);

caseStringComparison.InvariantCulture:
returnCultureInfo.InvariantCulture.CompareInfo.Compare(strA,strB,CompareOptions.None);

caseStringComparison.InvariantCultureIgnoreCase:
returnCultureInfo.InvariantCulture.CompareInfo.Compare(strA,strB,CompareOptions.IgnoreCase);

caseStringComparison.Ordinal:
returnCompareOrdinalHelper(strA,strB);

caseStringComparison.OrdinalIgnoreCase:
if(!strA.IsAscii()||!strB.IsAscii())
{
returnTextInfo.CompareOrdinalIgnoreCase(strA,strB);
}
returnCompareOrdinalIgnoreCaseHelper(strA,strB);
}
thrownewNotSupportedException(Environment.GetResourceString("NotSupported_StringComparison"));
}

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


publicstaticintCompareOrdinal(stringstrA,stringstrB)
{
if(strA==strB)
{
return0;
}
if(strA==null)
{
return-1;
}
if(strB==null)
{
return1;
}
returnCompareOrdinalHelper(strA,strB);
}


接下来看看String.CompareTo()方法的源代码:

[TargetedPatchingOptOut("PerformancecriticaltoinlineacrossNGenimageboundaries")]
publicintCompareTo(stringstrB)
{
if(strB==null)
{
return1;
}
returnCultureInfo.CurrentCulture.CompareInfo.Compare(this,strB,CompareOptions.None);
}

与类型参数为StringComparison.CurrentCulture的Compare方法相同。

另外StringComparer也实现了字符串比较方法Compare()方法。直接看源代码:

publicintCompare(objectx,objecty)
{
if(x==y)
{
return0;
}
if(x==null)
{
return-1;
}
if(y==null)
{
return1;
}
stringstr=xasstring;
if(str!=null)
{
stringstr2=yasstring;
if(str2!=null)
{
returnthis.Compare(str,str2);
}
}
IComparablecomparable=xasIComparable;
if(comparable==null)
{
thrownewArgumentException(Environment.GetResourceString("Argument_ImplementIComparable"));
}
returncomparable.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方法,是因为其对语言文化敏感。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: