IndexOf(char) 与 Contains(string) 在检查字符串中是否存在字符时的性能

Performance of IndexOf(char) vs Contains(string) for checking the presence of a character in a string

我想知道

string.IndexOf(char) 

string.Contains(string) 

目的是检查单个字符是否出现在string中。我知道根据要求我应该使用 string.Contains(string) 但这不是这个问题的重点。我确实尝试 disassemble mscorlib.dll 试图比较它们的实现,但我找不到

的实现
 string.IndexOf(char)

因为它是在 CLR 本身 中实现的。

的实施
 string.Contains(string)

虽然看起来很沉重

测试看看

  String source = new String('a', 10000000) + "b" + new String('c', 10000000);

  Stopwatch sw = new Stopwatch();

  sw.Start();

  // Just an estimation
  int result = source.IndexOf('b');
  // int result = source.IndexOf("b");
  // Boolean result = source.Contains("b");
  // Boolean result = source.Contains('b');

  sw.Stop();

  int time = sw.ElapsedMilliseconds;

在我的工作站(i5 3.2 GHz,.Net 5.0 64 位),Char38 毫秒[=需要大约 10 毫秒 27=] 对于 String

编辑: 表演的结果是

  IndexOf(Char)     10 -- Fastest
  IndexOf(String)   38 
  Contains(Char)   100 -- Slowest
  Contains(String)  41

所以IndexOf(String)Contains(String)大致相同

  1. 你应该写一个小的基准来找出答案。
  2. 我预测这个结果:因为 IndexOf(char) 是一个简单的循环并且 Contains()(和IndexOf(string))通常是两个嵌套循环, 前者会更快。

mscorlib.dll 的源代码在 Microsoft Reference Source 可用(并且在原始 post 时已经存在)。您可以在 String class 中看到 Contains(string) 是一个包装器

public bool Contains( string value ) {
    return ( IndexOf(value, StringComparison.Ordinal) >=0 );
}

around IndexOf 函数,就是用了extern InternalFindNLSStringEx 函数,那肯定很快。但由于显而易见的原因,没有 extern IndexOf(char) 函数那么快。 这就解释了为什么 IndexOf(string)Contains(string) 的计算速度几乎相同。但是要小心你的 becnhmarks,因为在 CLR 的深处它使用了某种缓存,我认为,所以一个函数的速度取决于你调用它的顺序 - 在另一个之前或之后。

这个问题在原来的 post 中没有出现,但是正如上面有人提到的,我们也来看看 Contains<char> 这是一个 Enumerable 扩展:

public static bool Contains<TSource>(this IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
{
    if (comparer == null) comparer = EqualityComparer<TSource>.Default;
    if (source == null) throw Error.ArgumentNull("source");
    foreach (TSource element in source)
        if (comparer.Equals(element, value)) return true;
    return false;
}

因此,它将按顺序对每个元素调用 Equals。这很简洁,允许您使用自定义比较器,但使用 IndexOf(char) 会更快。