【问题标题】:Is there a set of C# data readonly generic collections / data structures?是否有一组 C# 数据只读通用集合/数据结构?
【发布时间】:2013-02-01 16:15:25
【问题描述】:

我正在寻找一个只读通用集合库,它是与.NET v3.5 兼容的常见System.Collections.Generic; 集合的.NET 版本的镜像(或者更确切地说是实现或扩展)。

我猜 F# 可能有一些只读集合(但我不确定它们是否实现了 System.Collections.Generic 的接口)。除此之外,我宁愿不在服务器上安装 F#。我想我可以简单地部署 F# dll,如果可行的话,我怀疑是这样。

是否存在实现 System.Collections.Generic 中的接口并提供相同性能(或更好)特性的只读泛型集合类库?例如,IList 的随机访问数组支持的实现(只读)。

【问题讨论】:

  • 该命名空间中大多数集合的只读接口是在 4.5 中添加的。该集合不是不可变的,但您可以向其他人提供只读视图。如果集合通过这种视图公开,则它实际上是不可变的;出于所有意图和目的。
  • 您可以像部署任何其他程序集一样部署 F# 程序集——因此,如果您想在 C# 应用程序中使用 FSharp.Core 中的不可变集合类型,只需添加对它的引用并将其标记为“复制”本地”。
  • 现有 System.Collections.Generic 接口中定义的大部分方法对于不可变集合来说是无用的。例如,从IList<T> 接口,您不能实现 set_Item、Add、Clear、Insert、Remove 或 RemoveAt。在不可变集合上实现这些接口在某些情况下可能会很方便,但在大多数情况下会要求抛出异常。因此,F# 集合实现的唯一 System.Collections.Generic 接口是 IEnumerable<T>

标签: c# collections f#


【解决方案1】:

如果您想要不可变,而不仅仅是只读集合,您可能对Microsoft's preview of immutable collections 感兴趣。

System.Collections.Generic 中的大多数类都有对应项。

【讨论】:

  • 看起来很有希望,但仅适用于 .NET 4.5
【解决方案2】:

System.Collections.ObjectModel 中的ReadOnlyCollection<T>

它是您想要的任何集合的包装器。 最常见的是使用List<T> 并用ReadOnlyCollection<T> 包裹它。

然后,在公共实现中,您只授予对ReadOnlyCollection<T> 的访问权限并将List<T> 设置为私有。

public class MyClass
{
    private List<MyItemClass> list;
    public ReadOnlyCollection<MyItemClass> MyReadOnlyCollection { get; private set; }

    public MyClass()
    {
        list = new List<MyItemClass>() { ... };
        MyReadOnlyCollection = new ReadOnlyCollection<MyItemClass>(list);
    }
}

如果你想要一个“不可变对象”:

public class MyClass
{
    public ReadOnlyCollection<MyItemClass> MyReadOnlyCollection { get; private set; }

    public MyClass()
    {
        List<MyItemClass> list = new List<MyItemClass>() { ... };
        MyReadOnlyCollection = new ReadOnlyCollection<MyItemClass>(list);
    }
}

这样MyReadOnlyCollectionlist的状态不会改变。

【讨论】:

  • 我看过那个集合——我对 ISet、IDictionary、IList 等感兴趣。我希望这些结构中的每一个都有一个单一的来源,而不是来自 ObjectModel 的 ICollection 和 IList / ISet 从其他地方。看起来 ReadOnlyCollection 只是一个包装器。如果原始引用被修改,则 ReadOnlyCollection 被修改。我想,我的初衷是错误的——只读我的意思是不可变的。
  • @lucidquiet 是的,但您可以删除对基础集合的可见引用。然后,您将无法访问它。
  • @lucidquiet:你要求的是相互矛盾的东西。 ISetIDictionaryIList 是可变接口,因此您不会找到实现这些接口的不可变集合,除非它们为可变操作抛出异常。事实上,这就是 F# 的 dict 运算符所做的。
【解决方案3】:

您应该看看 System.Collection.ObjectModel。

这里有一个只读字典、列表和可观察列表。

它们可以很好地处理任何可枚举的东西。

【讨论】:

    【解决方案4】:

    根据您的要求,将集合公开为IEnumerable&lt;T&gt; 可能就足够了,它本质上是只读的:

    var list = new List<int> {1,2,3,4};
    var coll = list.AsEnumerable(); //read-only interface
    

    但是,调用者仍然可以将集合转换为具体类型以使其可变:

    var backToList = (List<int>)coll; //now it's mutable again
    

    您还可以选择使用ReadOnlyCollection&lt;T&gt;,它不存在上述问题:

    var readonlyCollection = list.AsReadOnly(); // returns a ReadOnlyCollection<int>
    

    【讨论】:

      猜你喜欢
      • 2011-02-01
      • 2016-01-22
      • 2016-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-17
      • 1970-01-01
      相关资源
      最近更新 更多