是String.Equals(string1.Substring(0,X),字符串2)比string1.StartsWith(字符串2)更好吗? [英] Is String.Equals(string1.Substring(0, x), string2) better than string1.StartsWith(string2)?

查看:244
本文介绍了是String.Equals(string1.Substring(0,X),字符串2)比string1.StartsWith(字符串2)更好吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的字符串比较使用测试URL路径 StringComparison.OrdinalIgnoreCase

MSDN给出了以下字符串比较建议此处,但不明确的为什么

MSDN示例(中途下上面的页面):

 公共静态布尔IsFileURI(字符串路径)
{
   path.StartsWith(FILE,StringComparison.OrdinalIgnoreCase);
   返回true;
}
 

MSDN建议:

不过,preceding示例使用String.StartsWith(字符串,StringComparison)方法来测试是否相等。由于比较的目的是测试订购串相等代替,一个较好的选择是调用Equals方法,如图下面的例子。

 公共静态布尔IsFileURI(字符串路径)
{
   如果(path.Length小于5)返回false;

   返回String.Equals(path.Substring(0,5),FILE:,
                    StringComparison.OrdinalIgnoreCase);
}
 

问:为什么MSDN建议的第二个例子是更好的

讨论要点:

  1. 显然,返回true; 在第一个例子是一个错误,应该是返回path.StartsWith(...); 我们可以放心地忽略这个bug的VB code是正确的。

  2. 创作比较平等之前的一个子似乎只能用另一个存储资源不仅仅是调用String.StartsWith()。

  3. 的长度和LT; 5测试是一个很好的短路,但是它可以与现有code也一样使用。

  4. 第二个例子可以被理解为更清晰code,但我关心的是性能。子串的创作似乎没有必要。

解决方案

纵观 StartsWith 方法使用dotPeek,它最终调用内部比较函数比较整个字符串,并根据比较的返回值返回boolean:

 返回TextInfo.CompareOrdinalIgnoreCaseEx(这,0值,0,value.Length,value.Length)== 0;
 

String.Equals 调用:

 返回TextInfo.CompareOrdinalIgnoreCase(这一点,值)== 0;
 

CompareOrdinalIgnoreCase 调用私有方法,其中dotPeek不显示,但我的直觉是,调用 StartsWith 遍历整个字符串,而由<$ C $称为C>过载等于只要平等才能确定停止。

如果性能是一个问题,同时尝试用这将是典型的为你的应用价值计量。


出于好奇,我试图测量两个,而且它似乎是等于是明显加快。当我运行code以下使用一个发布版本,等于几乎是两倍的速度 StartsWith

 使用系统;
使用System.Diagnostics程序;

命名空间ConsoleApplication1
{
    内部类节目
    {
        私有静态无效的主要(字串[] args)
        {
            VAR URL = "http://stackoverflow.com/questions/8867710/is-string-equalsstring1-substring0-x-string2-better-than-string1-startswit";
            VAR数=千万;
            VAR HTTP = FALSE;

            秒表SW = Stopwatch.StartNew();

            的for(int i = 0; I&LT;计数;我++)
            {
                的http = url.StartsWith(HTTP:,StringComparison.OrdinalIgnoreCase);
            }

            sw.Stop();

            Console.WriteLine(StartsWith:{0}毫秒,sw.ElapsedMilliseconds);

            sw.Restart();

            的for(int i = 0; I&LT;计数;我++)
            {
                的http = string.Equals(url.Substring(0,5),的http:,StringComparison.OrdinalIgnoreCase);
            }

            sw.Stop();

            Console.WriteLine(等于:{0}毫秒,sw.ElapsedMilliseconds);

            到Console.ReadLine();
        }
    }
}
 

I am using string comparisons to test URL paths using StringComparison.OrdinalIgnoreCase.

MSDN gives the following string comparison advice HERE, but does not clarify WHY:

MSDN Example (half-way down the above page):

public static bool IsFileURI(string path) 
{
   path.StartsWith("FILE:", StringComparison.OrdinalIgnoreCase);
   return true;
}

MSDN Advice:

"However, the preceding example uses the String.StartsWith(String, StringComparison) method to test for equality. Because the purpose of the comparison is to test for equality instead of ordering the strings, a better alternative is to call the Equals method, as shown in the following example."

public static bool IsFileURI(string path)
{
   if (path.Length < 5) return false;

   return String.Equals(path.Substring(0, 5), "FILE:", 
                    StringComparison.OrdinalIgnoreCase);
}

QUESTION: Why does MSDN suggest the second example is better?

Discussion points:

  1. Clearly the return true; in the first example is a bug and should be return path.StartsWith(...);. We can safely ignore this as a bug as the VB code is correct.

  2. Creation of a substring prior to comparing for equality would appear to only use another memory resource than just calling String.StartsWith().

  3. The Length < 5 test is a nice short-circuit, however it could be used with the prior code just the same.

  4. The second example could be construed as clearer code, but I am concerned with performance. The creation of the substring seems unnecessary.

解决方案

Looking at the StartsWith method using dotPeek, it eventually calls an internal comparison function that compares the entire string, and returns a boolean result based on the return value of that comparison:

return TextInfo.CompareOrdinalIgnoreCaseEx(this, 0, value, 0, value.Length, value.Length) == 0;

String.Equals calls:

return TextInfo.CompareOrdinalIgnoreCase(this, value) == 0;

CompareOrdinalIgnoreCase calls a private method, which dotPeek doesn't show, but my hunch is that the overload called by StartsWith traverses the entire string while the overload called by Equals stops as soon as equality can be determined.

If performance is a concern, try measuring both with values that will be typical for your application.


Out of curiousity, I tried measuring the two, and it does seem that Equals is noticeably faster. When I run the code below using a release build, Equals is nearly twice as fast as 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();
        }
    }
}

这篇关于是String.Equals(string1.Substring(0,X),字符串2)比string1.StartsWith(字符串2)更好吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆