【问题标题】:Read-only list or unmodifiable list in .NET 4.0.NET 4.0 中的只读列表或不可修改列表
【发布时间】:2009-06-11 22:13:20
【问题描述】:

据我所知,.NET 4.0 仍然缺少只读列表。为什么框架仍然缺少这个功能?这不是domain-driven design 最常见的功能之一吗?

Java 相对于 C# 的少数优势之一是 Collections.unmodifiablelist(list) 方法的形式,这在 IList 或 List 中似乎早就应该使用了。

使用IEnumerable<T> 是该问题的最简单解决方案 - 可以使用ToList 并返回一个副本。

【问题讨论】:

  • 似乎拥有真正只读List<T> 的唯一真正方法是编写自己的,据我所知,没有内置类支持所有“只读”功能List<T> 开箱即用,如 Contains、LINQ 查询等。

标签: c# java .net readonly-collection


【解决方案1】:

您正在寻找自 .NET2 以来一直存在的 ReadOnlyCollection

IList<string> foo = ...;
// ...
ReadOnlyCollection<string> bar = new ReadOnlyCollection<string>(foo);

List<string> foo = ...;
// ...
ReadOnlyCollection<string> bar = foo.AsReadOnly();

这将创建一个只读的视图,它反映了对包装集合所做的更改。

【讨论】:

  • 现在问这个问题我觉得有点愚蠢——而且不知道 ReadOnlyCollection
  • 不要 - 我也没有,当我去寻找同样的东西并找到你的问题时
  • 这是一门非常难找的课程。它在 System.Collections.ObjectModel 命名空间而不是 System.Collections.Generic 中,我希望在其中找到它。我想这是因为它在 Generic 命名空间存在之前就在那里。我仍然希望基类保留在 ObjectModel 中,并将泛型类添加到 Generic 中。我想他们有他们的理由,但我觉得这很烦人。
  • @BlueMonkMN :请参考此article 以了解它与 Collections.Generic 命名空间分开的原因。
  • 但这不是一个列表,它是一个集合。所以如果你使用它,你需要修改你所有的代码来使用Collection而不是List。
【解决方案2】:

对于喜欢使用接口的人: .NET 4.5 添加了通用的IReadOnlyList 接口,例如由List&lt;T&gt; 实现。

它类似于IReadOnlyCollection 并添加了一个Item 索引器属性。

【讨论】:

    【解决方案3】:

    框架中已经存在的ReadOnlyCollection 怎么样?

    【讨论】:

      【解决方案4】:

      如果列表的最常见模式是遍历所有元素,IEnumerable&lt;T&gt;IQueryable&lt;T&gt; 也可以有效地充当只读列表。

      【讨论】:

      • 如果您将 List 公开为 IEnumerable,那么消费者可以简单地将其转换回 List 并对其进行修改。
      • 当然,但这并不是一种防弹措施——您也可以阅读私有字段并追踪原始列表。它更像是描述它应该保持只读的意图。
      • 您也没有通过调用ToList() 来修改原始列表,只是一个副本
      • 注意IEnumerable并不是一套完整的“只读”方法,例如它不包含Contains这样的方法。
      【解决方案5】:

      在 2.0 中,您可以调用 AsReadOnly 来获取列表的只读版本。或者将现有的 IList 包装在 ReadOnlyCollection&lt;T&gt; 对象中。

      【讨论】:

      • 这相当于我所追求的 Collections.unmodifiablelist(list)
      • 我在 .NET 4 中错过了这一点,因为我使用的是 IList 而不是真正的 List。请务必注意 AsReadOnly 在 .NET 4 中仍然可用,只要您处理的是 List.
      【解决方案6】:

      【讨论】:

        【解决方案7】:

        在IEnumerable上创建一个扩展方法ToReadOnlyList(),然后

        IEnumerable<int> ints = new int[] { 1, 2, 3 };
        var intsReadOnly = ints.ToReadOnlyList();
        //intsReadOnly [2]= 9; //compile error, readonly
        

        这里是扩展方法

        public static class Utility
        {
            public static IReadOnlyList<T> ToReadOnlyList<T>(this IEnumerable<T> items)
            {
                IReadOnlyList<T> rol = items.ToList();
                return rol;
            }
        }
        

        也见Martin's answer

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-12-15
          • 2013-04-27
          • 1970-01-01
          • 2018-01-02
          • 1970-01-01
          • 2016-12-09
          • 2016-06-14
          • 2011-04-20
          相关资源
          最近更新 更多