简体   繁体   English

扩展方法如ToArray和ToList是按引用还是按值操作?

[英]Do extension methods like `ToArray` and `ToList` operate by reference or by value?

Let's say I have a private dictionary or a list in my class. 假设我班上有私人词典或清单。 I want to return a readonly enumerator so that others can iterate over the list, but not have access to modify the items. 我想返回一个只读的枚举数,以便其他人可以遍历列表,但无权修改项目。

Instead of creating a wrapper class around the original, I'd like to return copies of the original items/elements. 我不想返回原始的包装类,而是返回原始项目/元素的副本。 Will something like original.ToList<Type>().GetEnumerator() return a list with references to the original items, or a list with copies of the original items? original.ToList<Type>().GetEnumerator()返回一个包含原始项目引用的列表,还是一个包含原始项目副本的列表?

I should note that I also need indexing (ie accessing items by index, still not being able to modify them). 我应该注意,我还需要建立索引(即按索引访问项目,但仍然无法对其进行修改)。

The methods create a new instance of the collection, but the item references will still be to the old items. 这些方法将创建集合的新实例,但项目引用仍将是旧项目。 In other words, a consumer could not update your internal collection, but they could update the items themselves. 换句话说,消费者无法更新您的内部收藏,但是他们可以自己更新商品。

Assuming you have appropriate encapsulation around modifying the items, this approach will work, though it is a little memory-intensive for larger lists, since you need to allocate memory for each new item reference. 假设您具有适当的封装来修改项目,这种方法将起作用,尽管对于较大的列表来说这会占用大量内存,因为您需要为每个新项目引用分配内存。 That's one reason why returning a wrapper is often preferred: it reduces the extra memory required to a single instance of the wrapper class. 这就是为什么通常首选返回包装器的原因之一:它减少了包装器类的单个实例所需的额外内存。

ToList() and Torray() both work by value . ToList()Torray()按值工作。 They simply copy the values from the original IEnumerable<> to the new container. 他们只是将值从原始IEnumerable<>复制到新容器。

But the values being copied might very well be references. 但是复制的值很可能是参考。

The straight call to 直接拨打

original.ToList<MyType>()

will create a "shallow" copy: the list will be new, but the objects will be the same. 将创建一个“浅”副本:该列表将是新的,但对象将相同。

If you would prefer a "deep" copy, you can use LINQ to duplicate your items before adding them to the list: 如果您希望使用“深层”副本,则可以使用LINQ复制项目,然后再将它们添加到列表中:

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

Assuming that your class has a constructor that takes an instance of itself and produces a copy, similar to a copy constructor of C++, this would produce a list of copies of your objects. 假设您的类具有一个构造函数,该构造函数接受自身的实例并生成一个副本,类似于C ++的副本构造函数,则这将生成一个对象副本列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM