Array.Count () намного медленнее, чем List.Count ()

При использовании метода расширенияIEnumerable Count(), массив как минимум в два раза медленнее, чем список.

Function                      Count()
List                     2,299
int[]                         6,903

Откуда взялась разница?

Я понимаю, что оба называютCount собственностью :ICollection

Если тип источника реализует ICollection, эта реализация используется для получения количества элементов. В противном случае этот метод определяет количество.

Для списка это возвращаетList.Countи для массива,Array.Length, Более того,Array.Length должен быть быстрее, чем.List.Count

Ориентир:

class Program
{
    public const long Iterations = (long)1e8;

    static void Main()
    {
        var list = new List(){1};
        var array = new int[1];
        array[0] = 1;

        var results = new Dictionary();
        results.Add("List", Benchmark(list, Iterations));
        results.Add("int[]", Benchmark(array, Iterations));

        Console.WriteLine("Function".PadRight(30) + "Count()");
        foreach (var result in results)
        {
            Console.WriteLine("{0}{1}", result.Key.PadRight(30), Math.Round(result.Value.TotalSeconds, 3));
        }
        Console.ReadLine();
    }

    public static TimeSpan Benchmark(IEnumerable source, long iterations)
    {
        var countWatch = new Stopwatch();
        countWatch.Start();
        for (long i = 0; i < iterations; i++) source.Count();
        countWatch.Stop();

        return countWatch.Elapsed;
    }
}

Редактировать:

leppie а такжесукявляется ответы довольно удивительны, но я хочу добавить замечание.

Как сказал Джон Скит:

Фактически есть два эквивалентных блока, просто тестирующих различные типы интерфейса коллекции и использующих тот, который найден первым (если есть). Я нене знает, тестирует ли реализация .NET для ICollection или ICollection <T> во-первых, я мог бы проверить это, реализовав оба интерфейса, но, конечно, возвращая разные значения для каждого, но этоСкорее всего, перебор. Это недля коллекций с хорошим поведением не имеет значения, кроме небольшой разницы в производительности - мы хотим проверитьболее вероятный" Первый интерфейс, который я считаю, является общим.

Скорее всего, универсальный может произойти, но если вы инвертируете два, то есть вызовете не универсальное приведение перед универсальным, Array.Count () станет немного быстрее, чем List.Count (). С другой стороны, неуниверсальная версия медленнее для List.

Полезно знать, если кто-то хочет позвонитьCount() в цикле 1e8 итераций!

Function       ICollection Cast     ICollection Cast
List                1,268                   1,738         
Array               5,925                   1,683

Ответы на вопрос(4)

Ваш ответ на вопрос