public static void AddRange<T>(this IList<T> source, IEnumerable<T> newList)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (newList == null)
{
throw new ArgumentNullException(nameof(newList));
}
if (source is List<T> concreteList)
{
concreteList.AddRange(newList);
return;
}
foreach (var element in newList)
{
source.Add(element);
}
}
public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> items)
{
if (collection is null)
throw new ArgumentNullException(nameof(collection));
if (items is null)
throw new ArgumentNullException(nameof(items));
switch (collection)
{
case List<T> list:
list.AddRange(items);
break;
default:
foreach (var item in items)
{
collection.Add(item);
}
break;
}
}
4条答案
按热度按时间j1dl9f461#
因为一个接口应该易于实现,并且不包含“除了厨房之外的所有东西”。更好的问题是为什么
IList<T>
接口没有类似于IEnumerable<T>
接口的扩展方法。(用于就地Sort
、BinarySearch
...的扩展方法将很有用)kqhtkvqz2#
对于那些希望在IList上拥有“AddRange”、“Sort”等扩展方法的人,
下面是
AddRange
的扩展方法:我创建了一个小库来做这件事。我发现它比在每个项目上重做它的扩展方法更实用。
有些方法比List慢,但它们可以完成这项工作。
下面是让他们感兴趣的GitHub:
IListExtension repository
9q78igpj3#
实际上,除了
.Net platfom
开发人员和架构师,没有人能回答这个问题。在这个答案中,我将谈论非泛型类,但几乎我所有的话对泛型类也是正确的。
在我开始解释之前,我想对那些不知道的人提一下,
List<>
和所有IList
实现并不是根据通用编程和数据结构应该是List,通常是指 * 链表 *。表示可通过索引单独访问的对象集合。
所以,一般来说,阅读这个定义,你一定不会有“为什么
AddRange
没有呈现在IList
中“的问题,而是“为什么Add
呈现了"的问题。而且,说到Add
,它不在IList
接口中,而是在ICollection
接口中。这真伊萨奇怪。为什么呢?因为.Net标准中几乎所有的集合都继承了ICollection
。正因为如此,中有很多地方。Net源代码,我们可以看到Add
的实现,就像在Array类中一样(是的,Array
也实现了IList
):关于C#中的集合接口之间的关系,我可以说更多的东西(还有IReadOnlyList,它是在
IList
之后添加的,看起来像IList
应该是的东西)。但是我认为有足够的上下文,我们可以开始谈论IList
没有AddRange
,但List<>
有的具体原因。IList
实作都应该有AddRange
方法。正如我上面提到的,
Add
方法有一个问题。C#中的很多集合实际上都有它,但在调用它时会抛出NotSupportedException
。同样的情况(甚至更糟)。因此,只有List<>
需要此方法,但IList
的所有其他实现都不需要此方法。此外,那些开发人员,决定创建自己的IList
实现的用户必须实现AddRange
,这看起来不像是简单索引集合(即IList
)真正需要的东西。AddRange
强烈依赖于List<T>
实现。说到
List<>
类。它不是非泛型类List
。非泛型变量称为ArrayList
。而ArrayList
在数据结构上是Dynamic Array的某种同义词。我不知道为什么决定在泛型集合中将ArrayList
重命名为List
。但我认为这只会增加对C#中这些类的误解。所以,List<T>
实际上是一个动态数组。如果你一个一个地向动态数组添加大量的元素,动态数组会有很大的性能问题。所以,AddRange
是一个辅助,从某种意义上说,动态数组的必要方法。但是索引集合完全不需要,索引集合就是IList
。作为结论,我想说,
List<T>
和IList<T>
(就像ArrayList
和IList
),事实上,是实体,它们有不同的语义,你不能把它们看作是可互换的东西。但是在命名和接口关系方面有一些不好的决定,导致人们对List<T>
和IList<T>
之间关系的认识越来越不正确6ss1mwsb4#
从C#7开始,我们就有了模式匹配,我们可以轻松地使用它来调用性能更高的
List.AddRange()
方法,而不需要使用as
保存转换。