像ToArray`和`ToList`这样的扩展方法是通过引用还是通过值操作的?

时间:2012-08-01 21:57:14

标签: c#

假设我的课程中有私人字典或列表。我想返回一个只读枚举器,以便其他人可以遍历列表,但无权修改项目。

我想要返回原始项目/元素的副本,而不是围绕原始文件创建包装类。像original.ToList<Type>().GetEnumerator()之类的东西会返回一个列表,其中包含对原始项目的引用,或者包含原始项目副本的列表吗?

我应该注意到我还需要索引(即按索引访问项目,但仍然无法修改它们)。

3 个答案:

答案 0 :(得分:5)

方法创建集合的新实例,但项目引用仍将是旧项目。换句话说,消费者无法更新您的内部集合,但他们可以自行更新项目。

假设您在修改项目时有适当的封装,这种方法可行,尽管对于较大的列表来说它有点内存密集,因为您需要为每个新项目引用分配内存。这就是为什么返回包装器通常是首选的一个原因:它减少了包装类的单个实例所需的额外内存。

答案 1 :(得分:3)

ToList()Torray()都按值工作。他们只是将原始IEnumerable<>中的值复制到新容器中。

但是被复制的值很可能是引用。

答案 2 :(得分:2)

直接致电

original.ToList<MyType>()

将创建一个“浅”副本:列表将是新的,但对象将是相同的。

如果您更喜欢“深度”副本,可以使用LINQ复制项目,然后再将它们添加到列表中:

original.Select(item => new MyType(item)).ToList()

假设你的类有一个构造函数,它接受一个自身的实例并生成一个副本,类似于C ++的复制构造函数,这将生成一个对象的副本列表。