如何防止方法调用者修改返回的集合? [英] How to prevent a method caller from modifying a returned collection?

查看:88
本文介绍了如何防止方法调用者修改返回的集合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些方法可以将私有集合返回给调用者,并且我想防止调用者修改返回的集合。

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.


  1. 将集合包装在 ReadOnlyCollection< T>

  2. 通过执行之类的虚拟投影,返回由 Enumerable 类定义的LINQ迭代器之一。 list.Select(item => item)。实际上,我考虑使用 Where(item => true),因为返回的迭代器似乎更轻巧。

  3. 编写自定义包装。 / li>
  1. Wrapping the collection in ReadOnlyCollection<T>.
  2. Returning one of the LINQ iterators defined by the Enumerable class by performing a dummy projection like list.Select(item => item). Actually I consider using Where(item => true) because the returned iterator seems more lightweight.
  3. Writing a custom wrapper.

我不喜欢使用 ReadOnlyCollection< T> 实现 IList< T> 并调用 Add()或访问索引器将导致异常。虽然从理论上讲这是绝对正确的,但几乎没有实际代码检查 IList.T.IsReadOnly IList .IsFixedSize

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆