为什么使List <T> .AddRange方法成为通用方法对性能有害?

use*_*967 9 .net c# generics performance covariance

我正在深入阅读C#(第3版)和第13章,在c#4中讨论包含协变和逆变类型参数的部分,这个主张是:

对于List.AddRange该参数的类型的IEnumerable的<T>,所以在这种情况下,你把每个列表作为一个IEnumerable <IShape的> -something,不会有以前是不可能的.AddRange本来可以用它自己的类型参数写成泛型方法,但它没有 - 这样做会使一些优化变得困难或不可能.

有人能为这种说法提供一些理由吗?对我来说这是真的并不明显.

Min*_*neR 1

我猜它不是按原样编写的,void AddRange<T>(IEnumerable<T> items)因为它在IEnumerable<T>是 时进行了优化ICollection<T>。当IEnumerable<T>为 an 时ICollection<T>,AddRange 内部调用ICollection<T>.CopyTo,第一个参数为T[]。(请注意, a 的底层存储机制List<T>是 a T[])。

基类型的数组与派生类型的数组不同,因此您不能这样做,例如:

object[] objs = new object[4];
var collection = (new string[4]) as ICollection<string>;
collection.CopyTo(objs,0); //Cannot convert object[] to string[]
Run Code Online (Sandbox Code Playgroud)

这是“不可能”的优化。

您可以在此处查看源代码: https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,79de3e39e69a4811

似乎AddRange应该检查T[]List<T>,并Array.Copy在这些情况下执行 an ,但我猜是 -100 。Array.ToArray()您可能会对有些不起作用的事情感到有些惊讶。