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 位),Char
和 38 毫秒[=需要大约 10 毫秒 27=] 对于 String
编辑: 表演的结果是
IndexOf(Char) 10 -- Fastest
IndexOf(String) 38
Contains(Char) 100 -- Slowest
Contains(String) 41
所以IndexOf(String)
和Contains(String)
大致相同
- 你应该写一个小的基准来找出答案。
- 我预测这个结果:因为
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)
会更快。
我想知道
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 位),Char
和 38 毫秒[=需要大约 10 毫秒 27=] 对于 String
编辑: 表演的结果是
IndexOf(Char) 10 -- Fastest
IndexOf(String) 38
Contains(Char) 100 -- Slowest
Contains(String) 41
所以IndexOf(String)
和Contains(String)
大致相同
- 你应该写一个小的基准来找出答案。
- 我预测这个结果:因为
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)
会更快。