我正在使用字符串比较来使用StringComparison.OrdinalIgnoreCase
测试网址路径。
MSDN提供以下字符串比较建议HERE,但未澄清为什么:
MSDN示例(在上一页的中间):
public static bool IsFileURI(string path)
{
path.StartsWith("FILE:", StringComparison.OrdinalIgnoreCase);
return true;
}
MSDN建议:
“但是,前面的示例使用String.StartsWith(String,StringComparison)方法来测试是否相等。因为比较的目的是测试相等而不是排序字符串,更好的选择是调用Equals方法,如下例所示。“
public static bool IsFileURI(string path)
{
if (path.Length < 5) return false;
return String.Equals(path.Substring(0, 5), "FILE:",
StringComparison.OrdinalIgnoreCase);
}
问题:为什么MSDN建议第二个例子更好?
讨论要点:
显然,第一个示例中的return true;
是一个错误,应该是return path.StartsWith(...);
。 我们可以放心地忽略这一点,因为VB代码是正确的。
在比较相等性之前创建子字符串似乎只使用另一个内存资源,而不仅仅是调用String.StartsWith()。
长度&lt; 5测试是一个很好的短路,但它可以与之前的代码一样使用。
第二个例子可以被解释为更清晰的代码,但我关注的是性能。似乎没有必要创建子字符串。
答案 0 :(得分:4)
使用dotPeek查看StartsWith
方法,它最终调用一个比较整个字符串的内部比较函数,并根据该比较的返回值返回一个布尔结果:
return TextInfo.CompareOrdinalIgnoreCaseEx(this, 0, value, 0, value.Length, value.Length) == 0;
String.Equals
来电:
return TextInfo.CompareOrdinalIgnoreCase(this, value) == 0;
CompareOrdinalIgnoreCase
调用一个私有方法,dotPeek没有显示,但我的预感是StartsWith
调用的重载遍历整个字符串,而Equals
调用的重载停止为很快就可以确定平等。
如果需要考虑性能问题,请尝试使用适用于您应用的典型值来测量两者。
出于好奇,我尝试测量这两个,看起来Equals
明显更快。当我使用发布版本运行下面的代码时,Equals
的速度几乎是StartsWith
的两倍:
using System;
using System.Diagnostics;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
var url = "http://stackoverflow.com/questions/8867710/is-string-equalsstring1-substring0-x-string2-better-than-string1-startswit";
var count = 10000000;
var http = false;
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
http = url.StartsWith("http:", StringComparison.OrdinalIgnoreCase);
}
sw.Stop();
Console.WriteLine("StartsWith: {0} ms", sw.ElapsedMilliseconds);
sw.Restart();
for (int i = 0; i < count; i++)
{
http = string.Equals(url.Substring(0, 5), "http:", StringComparison.OrdinalIgnoreCase);
}
sw.Stop();
Console.WriteLine("Equals: {0} ms", sw.ElapsedMilliseconds);
Console.ReadLine();
}
}
}
答案 1 :(得分:1)
答案位于您在Ordinal String Operations
标题下提供的代码示例的正下方。
.NET Framework中的字符串可以包含嵌入的空字符。 序数和文化敏感之间最明显的差异之一 比较(包括使用不变文化的比较) 涉及在字符串中处理嵌入的空字符。这些 使用String.Compare和时忽略字符 String.Equals执行区分文化比较的方法 (包括使用不变文化的比较)。结果是, 在文化敏感的比较中,包含嵌入null的字符串 字符可以被认为等于没有的字符串。
重要
尽管字符串比较方法忽略了嵌入式null 字符串,字符串搜索方法,如String.Contains, String.EndsWith,String.IndexOf,String.LastIndexOf和 String.StartsWith没有。
意味着使用序数比较的String.StartsWith
和String.Equals
将返回不同的结果。也就是说,使用序数比较的全部目的是防止土耳其系统上的人们绕过安全问题(忽略案例时"f" != "F"
)。意味着,如果测试使用了"FIL\0E:"
String.StartsWith
的文件URI,某人仍然可以绕过安全问题