查看字符串是否包含C#中的另一个字符串的最快,不区分大小写的方法是什么?

hsp*_*ain 11 .net c# string

编辑2:

确认我的性能问题是由于对StringExtensions类的静态函数调用造成的.一旦删除,IndexOf方法确实是实现此目的的最快方法.

查看字符串是否包含C#中的另一个字符串的最快,不区分大小写的方法是什么?我在这里看到了Case不敏感的'Contains(string)'这个帖子的公认解决方案,但是我已经做了一些初步的基准测试,看起来使用该方法会导致在测试时对较大的字符串(> 100个字符)调用较慢的数量级无法找到字符串.

以下是我所知道的方法:

指数:

public static bool Contains(this string source, string toCheck, StringComparison comp)
{
    if (string.IsNullOrEmpty(toCheck) || string.IsNullOrEmpty(source))
        return false;

    return source.IndexOf(toCheck, comp) >= 0;
} 
Run Code Online (Sandbox Code Playgroud)

ToUpper的:

source.ToUpper().Contains(toCheck.ToUpper());
Run Code Online (Sandbox Code Playgroud)

正则表达式:

bool contains = Regex.Match("StRiNG to search", "string", RegexOptions.IgnoreCase).Success;
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,这实际上是平均最快的方式,为什么呢?

编辑:

这是我用来突出性能差异的简单测试应用程序.使用它,我看到ToLower()为16 ms,ToUpper为18 ms,StringExtensions.Contains()为140 ms:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;

namespace ScratchConsole
{
    class Program
    {
    static void Main(string[] args)
    {
        string input = "";
        while (input != "exit")
        {
            RunTest();
            input = Console.ReadLine();
        }
    }

    static void RunTest()
    {
        List<string> s = new List<string>();
        string containsString = "1";
        bool found;
        DateTime now;
        for (int i = 0; i < 50000; i++)
        {
            s.Add("AAAAAAAAAAAAAAAA AAAAAAAAAAAA");
        }

        now = DateTime.Now;
        foreach (string st in s)
        {
            found = st.ToLower().Contains(containsString);
        }
        Console.WriteLine("ToLower(): " + (DateTime.Now - now).TotalMilliseconds);

        now = DateTime.Now;
        foreach (string st in s)
        {
            found = st.ToUpper().Contains(containsString);
        }
        Console.WriteLine("ToUpper(): " + (DateTime.Now - now).TotalMilliseconds);


        now = DateTime.Now;
        foreach (string st in s)
        {
            found = StringExtensions.Contains(st, containsString, StringComparison.OrdinalIgnoreCase);
        }
        Console.WriteLine("StringExtensions.Contains(): " + (DateTime.Now - now).TotalMilliseconds);

    }
}

public static class StringExtensions
{
    public static bool Contains(this string source, string toCheck, StringComparison comp)
    {
        return source.IndexOf(toCheck, comp) >= 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

}

aep*_*eus 15

由于ToUpper实际上会导致创建一个新字符串,所以StringComparison.OrdinalIgnoreCase会更快,同样,正则表达式对于像这样的简单比较有很多开销.也就是说,String.IndexOf(String,StringComparison.OrdinalIgnoreCase)应该是最快的,因为它不涉及创建新的字符串.

我猜想(我再去)RegEx有更好的最坏情况,因为它如何评估字符串,IndexOf将始终进行线性搜索,我猜(并再次)RegEx使用的东西稍好一些.RegEx也应该有一个最好的案例,可能会比IndexOf更接近(尽管不是很好)(由于它的语言更加复杂).

15,000 length string, 10,000 loop

00:00:00.0156251 IndexOf-OrdinalIgnoreCase
00:00:00.1093757 RegEx-IgnoreCase 
00:00:00.9531311 IndexOf-ToUpper 
00:00:00.9531311 IndexOf-ToLower

Placement in the string also makes a huge difference:

At start:
00:00:00.6250040 Match
00:00:00.0156251 IndexOf
00:00:00.9687562 ToUpper
00:00:01.0000064 ToLower

At End:
00:00:00.5781287 Match
00:00:01.0468817 IndexOf
00:00:01.4062590 ToUpper
00:00:01.4218841 ToLower

Not Found:
00:00:00.5625036 Match
00:00:01.0000064 IndexOf
00:00:01.3750088 ToUpper
00:00:01.3906339 ToLower
Run Code Online (Sandbox Code Playgroud)

  • 没有评论的下降率就像没有狗的遛狗一样...... (5认同)
  • 我想我应该说"我99%肯定,但是当提问的人应该"时,不会花时间进行剖析." (2认同)