Listar a implementação <T> .AddRange abaixo do ideal

A criação de perfil do meu aplicativo C # indicou que um tempo significativo é gasto emList<T>.AddRange. O uso do Refletor para examinar o código neste método indicou que ele chamaList<T>.InsertRange que é implementado como tal:

public void InsertRange(int index, IEnumerable<T> collection)
{
    if (collection == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
    }
    if (index > this._size)
    {
        ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
    }
    ICollection<T> is2 = collection as ICollection<T>;
    if (is2 != null)
    {
        int count = is2.Count;
        if (count > 0)
        {
            this.EnsureCapacity(this._size + count);
            if (index < this._size)
            {
                Array.Copy(this._items, index, this._items, index + count, this._size - index);
            }
            if (this == is2)
            {
                Array.Copy(this._items, 0, this._items, index, index);
                Array.Copy(this._items, (int) (index + count), this._items, (int) (index * 2), (int) (this._size - index));
            }
            else
            {
                T[] array = new T[count];          // (*)
                is2.CopyTo(array, 0);              // (*)
                array.CopyTo(this._items, index);  // (*)
            }
            this._size += count;
        }
    }
    else
    {
        using (IEnumerator<T> enumerator = collection.GetEnumerator())
        {
            while (enumerator.MoveNext())
            {
                this.Insert(index++, enumerator.Current);
            }
        }
    }
    this._version++;
}

private T[] _items;

Pode-se argumentar que a simplicidade da interface (com apenas uma sobrecarga de InsertRange) justifica a sobrecarga de desempenho da verificação e conversão do tipo de tempo de execução. Mas qual poderia ser a razão por trás das três linhas que indiquei com(*) ? Eu acho que poderia ser reescrito para a alternativa mais rápida:

is2.CopyTo(this._items, index);

Você vê algum motivo para não usar essa alternativa mais simples e aparentemente mais rápida?

Editar:

Obrigado pelas respostas. Portanto, a opinião do consenso é que essa é uma medida protetora contra a coleta de entradas que implementa o CopyTo de maneira defeituosa / maliciosa. Para mim, parece um exagero pagar constantemente o preço de 1) verificação do tipo de tempo de execução 2) alocação dinâmica da matriz temporária 3) duplicar a operação de cópia, quando tudo isso poderia ter sido salvo ao definir 2 ou mais sobrecargas de InsertRange um recebendoIEnumerable como agora, o segundo recebendo umList<T>terceiro obtendoT[]. Os dois últimos poderiam ter sido implementados para rodar duas vezes mais rápido do que no caso atual.

Edição 2:

Eu implementei uma classe FastList, idêntica à List, exceto que ela também fornece uma sobrecarga de AddRange, que recebe um argumento T []. Essa sobrecarga não precisa da verificação dinâmica do tipo e da cópia dupla de elementos. Criei o perfil desse FastList.AddRange em relação a List.AddRange adicionando matrizes de 4 bytes 1000 vezes a uma lista que estava inicialmente vazia. Minha implementação supera a velocidade do padrão List.AddRange com um fator de 9 (nove!). O List.AddRange ocupa cerca de 5% do tempo de execução em um dos cenários de uso mais importantes do nosso aplicativo. Substituir List por uma classe que fornece um AddRange mais rápido pode melhorar o tempo de execução do aplicativo em 4%.

questionAnswers(3)

yourAnswerToTheQuestion