【问题标题】:C# return non-modifiable listC# 返回不可修改的列表
【发布时间】:2011-04-20 06:26:18
【问题描述】:

我有一个包含List<Item> 的类我在返回这个的类上有一个getter。我可以做些什么来确保调用的用户不能修改返回的列表? (因为它是引用类型 - 我相信对返回引用的更改会影响存储在源对象中的列表)

【问题讨论】:

  • 如果您放宽了必须实际返回 List 的限制,您可以简单地返回 IEnumerable<T>,它具有 .Count().ElementAt() 方法,如果您枚举,则以 O(1) 速度执行集合实现IList<T>。在这种情况下,用户只有在明确投出它时才能进入列表,这将违反您的公共合同。

标签: c# .net properties readonly modifier


【解决方案1】:

返回用ReadOnlyCollection<T> 包裹的列表。

  public ReadOnlyCollection<Item> MyROList {
    get { return new ReadOnlyCollection<Item>(myList); }
  }

  private List<Item> myList = new List<Item>();

更多详情elsewhere on SO

根据您的类的使用情况,您可以在构造时分配ReadOnlyCollection 并将其链接到底层List。如果您期望始终或大部分时间都需要此属性,并且当时底层的List 已经到位,那么这是明智的。否则,您可以保留ReadOnlyCollection&lt;Item&gt; 类成员null,如果它是null,则在getter 中按需分配它(考虑线程安全)。

【讨论】:

  • 感谢您的回答。将集合包装在构造函数中的 ReadOnlyCollection 中不是更好吗 - 这样它只完成一次,而不是每次都做。当然,我的对象要重一些——因为我有一个额外的成员。但可能比每次都创建新对象更好?
  • ReadOnlyCollection 是源集合的实时副本。当源集合发生变化时,ReadOnlyCollection 也会发生变化。
【解决方案2】:

您希望 您的 类将来所做的任何更改都反映在返回的列表中吗?如果是这样,只需

return new ReadOnlyCollection<T>(list);

会好的。

但是,如果您想返回一个 nothing 将来会修改的集合(即原始列表的完全独立副本),您可能希望使用:

return new ReadOnlyCollection<T>(list.ToList());

(使用 LINQ 的 ToList 方法是一种非常简单的克隆列表的方法。)

请注意,如果列表的元素类型是可变引用类型,那么对引用对象中数据的更改当然对所有人都是可见的。

【讨论】:

  • list.AsReadOnly() / list.ToList().AsReadOnly()List&lt;T&gt; 的简洁替代品。对于一般的IList&lt;T&gt;ReadOnlyCollection&lt;T&gt; 的构造函数可能是最好的选择。
  • +1 感谢您的示例。很高兴知道 ToList 可用于克隆列表。
  • @Jon:将集合包装在构造函数中的 ReadOnlyCollection 中不是更好吗 - 这样它只完成一次,而不是每次都做。当然,我的对象要重一些——因为我有一个额外的成员。但可能比每次都创建新对象更好?感谢您的回答。
  • @Ani:我认为最好返回一个ReadOnlyCollection&lt;T&gt; - 并在 API 中明确说明 - 绝对清楚地表明调用者不能向其中添加项目。如果有一个表示只读列表的接口就好了,但是没有:(
  • @aip.cd.aish:这是一个相当轻量级的对象,但我猜这取决于它被调用的频率。为这个设置另一个字段感觉有点奇怪,但在某些情况下它可能有意义,是的。
猜你喜欢
  • 2010-11-02
  • 2010-12-15
  • 2014-09-21
  • 2017-03-23
  • 1970-01-01
  • 2011-10-27
  • 1970-01-01
  • 2020-07-22
  • 1970-01-01
相关资源
最近更新 更多