首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么使List<T>.AddRange方法成为一个通用的方法会对性能造成不良影响?

为什么使List<T>.AddRange方法成为一个通用的方法会对性能造成不良影响?
EN

Stack Overflow用户
提问于 2018-08-08 10:30:44
回答 2查看 720关注 0票数 9

我深入阅读了C# (第3版),在第13章中,在讨论在c# 4中包含协变和反变类型参数的一节中,提出了这样的主张:

List.AddRange的参数是IEnumerable类型,因此在本例中,您将每个列表视为以前不可能的IEnumerable -something。AddRange本来可以用自己的类型参数编写成一个泛型方法,但它不是这样做的--这样做会使一些优化变得困难或不可能。

有人能为这一说法提供一些理由吗?对我来说,为什么这是真的还不清楚。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-08-08 11:45:48

我想它不是像void AddRange<T>(IEnumerable<T> items)那样编写的,是因为它在IEnumerable<T>ICollection<T>时所做的优化。当IEnumerable<T>ICollection<T>时,AddRange内部调用ICollection<T>.CopyTo,其中的第一个参数是T[]。(请注意,List<T>的底层存储机制是T[])。

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

代码语言:javascript
复制
object[] objs = new object[4];
var collection = (new string[4]) as ICollection<string>;
collection.CopyTo(objs,0); //Cannot convert object[] to string[]

这是一种“不可能”的优化。

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

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

票数 1
EN

Stack Overflow用户

发布于 2018-08-08 10:42:57

我认为这样做的原因是,IEnumerable<T>可能只包含类型/实现接口T的对象,并且需要对AddRange<T2>中的每个元素进行检查。

让我们尝试一些可能与通用AddRange崩溃的代码。

代码语言:javascript
复制
public class MyClass1 : IFoo, IBar
{
  /* some code */
}

public class MyClass2 : IFoo
{
  /* some code */
}

var fooList = new List<IFoo>
{
  new MyClass1(),
  new MyClass2()
}
var barList = new List<IBar>();
barList.AddRange<IFoo>(fooList);

现在,问题是,它应该如何反应?您可以将MyClass1的对象添加到barList,因为它实现了IBar,但是当您尝试添加MyClass2时会发生什么呢?在添加元素之前,我们需要检查列表中的每个元素,以防止抛出异常。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51744440

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档