如何防止方法调用者修改返回的集合? [英] How to prevent a method caller from modifying a returned collection?
问题描述
我有一些方法可以将私有集合返回给调用者,并且我想防止调用者修改返回的集合。
I have methods returning private collections to the caller and I want to prevent the caller from modifying the returned collections.
private readonly Foo[] foos;
public IEnumerable<Foo> GetFoos()
{
return this.foos;
}
目前,私有集合是固定数组,但将来如果需要在运行时添加新项目,则collection可能会成为列表。
At the moment the private collection is a fixed array, but in the future the collection might become a list if the need for adding new items at run time arises.
有几种解决方案可以防止调用方修改集合。返回 IEnumerable< T>
是最简单的解决方案,但是调用方仍可以将返回值向上转换为 IList< T>
并修改集合。
There are several solutions to prevent the caller from modifying the collection. Returning IEnumerable<T>
is the simplest solution, but the caller can still up-cast the return value to IList<T>
and modify the collection.
((IList<Foo>)GetFoos())[0] = otherFoo;
克隆集合具有明显的缺点,即有两个集合可以独立发展。到目前为止,我已经考虑了以下选项。
Cloning the collections has the obvious disadvantage that there are two collections that can evolve independently. So far I have considered the following options.
- 将集合包装在
ReadOnlyCollection< T> $ c $中c>。
- 通过执行
之类的虚拟投影,返回由
。实际上,我考虑使用Enumerable
类定义的LINQ迭代器之一。 list.Select(item => item)Where(item => true)
,因为返回的迭代器似乎更轻巧。 - 编写自定义包装。 / li>
- Wrapping the collection in
ReadOnlyCollection<T>
. - Returning one of the LINQ iterators defined by the
Enumerable
class by performing a dummy projection likelist.Select(item => item)
. Actually I consider usingWhere(item => true)
because the returned iterator seems more lightweight. - Writing a custom wrapper.
我不喜欢使用 ReadOnlyCollection< T>
实现 IList< T>
并调用 Add()
或访问索引器将导致异常。虽然从理论上讲这是绝对正确的,但几乎没有实际代码检查 IList.T.IsReadOnly
或 IList
。
What I don't like about using ReadOnlyCollection<T>
is that it implements IList<T>
and calling Add()
or accessing the indexer will cause exceptions. While this is absolutly correct in theory, almost no real code checks IList<T>.IsReadOnly
or IList<T>.IsFixedSize
.
使用LINQ迭代器-我将代码包装在扩展方法 MakeReadOnly()
中-防止了这种情况
Using the LINQ iterators - I wrapped the code in an extension method MakeReadOnly()
- prevents this scenario, but it has the taste of a hack.
编写自定义包装?重新发明轮子?
Writing a custom wrapper? Reinventing the wheel?
有任何想法,考虑或其他解决方案吗?
Any thoughts, considerations, or other solutions?
在标记此问题时,我发现了此堆栈溢出问题我以前没有注意到。乔恩·斯凯特(Jon Skeet)也建议使用 LINQ hack,但使用 Skip(0)
更为有效。
While tagging this question, I discovered this Stack Overflow question I didn't notice before. Jon Skeet suggest to use the "LINQ hack", too, but even more efficient using Skip(0)
.
推荐答案
很遗憾,无法完全实现精确您在当前版本的框架中正在寻找的东西。它只是在具体类型和界面样式上都没有可索引的不可变/只读集合的概念。
Unfortunately there is no way to achieve exactly what you are looking for in the current version of the framework. It simply has no concept of an indexable immutable / read-only collection on both the concrete type and interface style.
正如您所指出的, ReadOnlyCollection< T>
在具体类型方面可以正常工作。但是没有相应的实现接口也是静态只读的。
As you pointed out, ReadOnlyCollection<T>
works OK on the concrete type side. But there is no corresponding interface to implement which is also statically read-only.
您唯一的选择是...
You're only real choice is to ...
- 定义您自己的收集类
- 仅实现
IEnumerable< T>
或定义您的集合所实现的需求只读接口。
- Define your own collection class
- Either only implement
IEnumerable<T>
or define a need read-only interface which your collection implements.
这篇关于如何防止方法调用者修改返回的集合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!