Потенциально, AddRange
может проверить, где переданное ему значение реализует IList
или IList<T>
. Если это так, он может узнать, сколько значений находится в диапазоне, и, следовательно, сколько места ему нужно выделить ... тогда как цикл foreach
может потребоваться перераспределить несколько раз.
Кроме того, даже после выделения, List<T>
может использовать IList<T>.CopyTo
для выполнения массового копирования в базовый массив (для диапазонов, которые реализуют IList<T>
, конечно.)
Я подозреваю, что вы обнаружите, что если вы попробуете свой тест еще раз, но вместо List<T>
вместо *1016* будете использовать Enumerable.Range(0, 100000)
, то оба будут занимать примерно одинаковое время.