Array.Contains运行速度非常慢,任何人都可以轻松一点?

col*_*ang 8 c# linq

我已经做了一些关于List.Contains,Array.Contains,IEnumerable.Contains,ICollection.Contains和IList.Contains的基准测试.

结果是:

array pure 00:00:45.0052754 // 45 sec, slow
array as IList 00:00:02.7900305
array as IEnumerable 00:00:46.5871087 // 45 sec, slow
array as ICollection 00:00:02.7449889
list pure 00:00:01.9907563
list as IList 00:00:02.6626009
list as IEnumerable 00:00:02.9541950
list as ICollection 00:00:02.3341203
Run Code Online (Sandbox Code Playgroud)

我发现如果Array.Contains直接调用会很慢(这相当于调用IEnumerable)

另外我觉得奇怪的是,MSDN数组页面没有contains在扩展方法部分列出的方法.

示例代码:

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

namespace arrayList
{
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch watch = new Stopwatch();
            Int64 n = 100000000;
            Int64[] myarray = new Int64[] { 1, 2, 3 };
            List<Int64> mylist = new List<Int64>(myarray);
            watch.Start();
            for (Int64 j = 0; j < n; j++)
            {

                bool i = myarray.Contains(2);

            }
            watch.Stop();
            Console.WriteLine("array pure {0}", watch.Elapsed);

            watch.Restart();
            for (Int64 j = 0; j < n; j++)
            {

                bool i = (myarray as IList<Int64>).Contains(2);

            }
            watch.Stop();
            Console.WriteLine("array as IList {0}",watch.Elapsed);

            watch.Restart();
            for (Int64 j = 0; j < n; j++)
            {

                bool i = (myarray as IEnumerable<Int64>).Contains(2);

            }
            watch.Stop();
            Console.WriteLine("array as IEnumerable {0}",watch.Elapsed);
            watch.Restart();
            for (Int64 j = 0; j < n; j++)
            {

                bool i = (myarray as ICollection<Int64>).Contains(2);

            }
            watch.Stop();
            Console.WriteLine("array as ICollection {0}",watch.Elapsed);

            watch.Restart();
            for (Int64 j = 0; j < n; j++)
            {

                bool i = mylist.Contains(2);

            }
            watch.Stop();
            Console.WriteLine("list pure {0}", watch.Elapsed);

            watch.Restart();
            for (Int64 j = 0; j < n; j++)
            {

                bool i = (mylist as IList<Int64>).Contains(2);

            }
            watch.Stop();
            Console.WriteLine("list as IList {0}", watch.Elapsed);

            watch.Restart();
            for (Int64 j = 0; j < n; j++)
            {

                bool i = (mylist as IEnumerable<Int64>).Contains(2);

            }
            watch.Stop();
            Console.WriteLine("list as IEnumerable {0}", watch.Elapsed);
            watch.Restart();
            for (Int64 j = 0; j < n; j++)
            {

                bool i = (mylist as ICollection<Int64>).Contains(2);

            }
            watch.Stop();
            Console.WriteLine("list as ICollection {0}", watch.Elapsed);
            Console.ReadKey();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Ale*_*kov 0

猜测:IList/List 使用 ICollection.Contains 直接使用索引遍历集合中的元素。

Array 和 IEnumerable 版本使用 IEnumerable.Contains,这需要创建枚举器并运行类型迭代代码(如 MoveNext 调用)。