为什么 List<T>.IndexOf() 比 List<T>.Contains() 快很多?

16
我有一个包含150K个元素的List。IndexOf()方法的平均工作时间比Contains()方法慢4倍。我尝试使用int类型的List,对于字符串类型的List,IndexOf()方法稍微快一些。
我只发现了一个主要的差异,那就是TargetedPatchingOptOut属性。MSDN解释如下:
表示应用此属性的.NET Framework类库方法不太可能受到维护发布的影响,因此有资格穿过本机图像生成器(NGen)映像进行内联。
这个属性可能是造成这种行为的原因吗?为什么Contains()方法没有这样的属性?
提前感谢您的回答。
编辑:我的代码类似于这样:
List<int> list = CommonHelper.GetRandomList(size);

long min = long.MaxValue;
long max = 0;
long sum = 0;

foreach (var i in list)
{
    m_stopwatch.Reset();
    m_stopwatch.Start();
    list.Contains(i); // list.IndexOf(i);
    m_stopwatch.Stop();

    long ticks = m_stopwatch.ElapsedTicks;

    if (ticks < min)
        min = ticks;

    if (ticks > max)
        max = ticks;

    sum += ticks;
}

long averageSum = sum / size;

编辑2:

我编写了与IndexOf()相同的代码,但它比Contains()运行得更慢。


1
这种情况下的数据是什么? - Marc Gravell
你能为我们制作一个简短的可重现测试,以展示这种行为吗? - Merlyn Morgan-Graham
你为什么有一个包含150K元素的列表?如果你需要遍历它,可能是因为你选择了错误的数据结构。 - Kobi
1
Kobi,我在生产环境中没有这样的列表,是在尝试不同的数据结构时发现的。 - Pavel Belousov
谢谢你的建议。让我节省了至少一半的时间。 - tim
显示剩余7条评论
1个回答

4
他们各自根据MSDN条目略微不同地到达确定相等性的方法。请查看每个条目的“备注”:List<T>.IndexOf使用EqualityComparer<T>.Defaulthttp://msdn.microsoft.com/en-us/library/e4w08k17.aspx。而List<T>.Contains使用IEquatable<T>.Equalshttp://msdn.microsoft.com/en-us/library/bhkz42b3.aspx。即使它们最终调用相同的方法来确定相等性(正如在这里肯定的那样),它们采取了不同的路线,因此这可能是原因。考虑到“4倍差异”似乎并不是实际情况,一些离线装箱可能会解释部分差异,特别是在一个150k大小的数据集中。

有趣。这种差异背后的逻辑是什么? - Thilo
我真的不知道;事实上,它们看起来如此相似,以至于我几乎没有检查它们用来测试相等性的方法。 - Andrew Barber
你不觉得 IEquatable 应该更快吗?而且 x4 的差距似乎相当大。 - Kobi
@Kobi;这也是我的初步想法。不过,今晚我的头脑有些迷糊,无法深入挖掘。哈哈 - Andrew Barber
我表达得有点不恰当;我的观点是比较方式存在轻微差异。 - Andrew Barber
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接