代码之家  ›  专栏  ›  技术社区  ›  SoftMemes

在.NET中表示不可变列表的最佳方法是什么?

  •  5
  • SoftMemes  · 技术社区  · 14 年前

    我最近开始使用f来“真正的工作”,并重新发现了不可变数据结构的美,如f中受歧视的联合和记录。我还发现它们在C中的使用非常直接,特别是因为它们不需要对F运行时有任何直接依赖性。然而,当涉及到在这些结构中表示列表时,我还没有找到一个理想的解决方案。

    我的第一个尝试是将列表键入seq<'a>(C_World中的IEnumerable),它提供了一个很好的通用收集界面,而不导出任何方法来像icolection<>及其朋友那样改变收集。但是,由于我无法控制区分联合或记录的构造函数,因此这些类型的实例的创建者可以提供一个IEnumerable实现,该实现在使用时可能会更改或引发(例如LINQ表达式)。因此,IEnumerable在证明该值是不可变的并且因此是线程安全的方面不会给予编译器任何帮助。

    我目前的策略是使用f_list类型,它确实保证了一个不可变的集合,但是增加了对f_runtime的依赖性,并且在非f_projects中使用时看起来有点过时。但是,它允许f模式匹配,而IEnumerable<>不允许。在列表的实际表示中,它也没有给出任何选择,在某些情况下(例如原始值的大列表),f列表表示并不真正适合。

    我真正想看到的是.NET中的不可变数组类型,它与普通数组一样简洁,但编译器保证不会发生变化。我欢迎康斯特作为C++,虽然它不太可能发生。同时,我还有其他的选择吗?

    4 回复  |  直到 11 年前
        1
  •  7
  •   JaredPar    14 年前

    如果您想要的是一个不可变的数组实现,那么您可以使用如下的方法

    public sealed class ImmutableArray<T> : IEnumerable<T>{
      private readonly T[] m_array;
      public T this[int index] {
        get { return m_array[index]; }
      }
      public int Length {
        get { return m_array.Length; }
      }
      public ImmutableArray(IEnumerable<T> enumerable) {
        m_array = enumerable.ToArray();
      }
      // IEnumerable<T> implementation ommitted
    }
    
        2
  •  2
  •   Richard    14 年前

    将普通数组包装为 ReadOnlyCollection<T> 实例:

    var readOnlyData = new ReadOnlyCollection<TheType>(theRealCollection);
    

    (注意,这不会复制基础集合,但保留引用和修改 IList<T> 实现等以引发异常。)

        3
  •  1
  •   Matt Warren    14 年前

    我建议你看看 Eric Lippert's 系列 immutability 这是一本非常有用的书。第4部分关于A immutable queue 会是一个很好的开始的地方。

        4
  •  1
  •   kimsk    11 年前

    微软发布了一个稳定版本的 Immutable collections 金块包。它不带 ImmutableArray 然而。但这些不变的数据结构应该非常有用。

    • 不可变主义者
    • 不变字典
    • 不变的或附加的
    • 不可变哈希集
    • 不变的排序集
    • 不可变栈
    • 不可变队列

    http://blogs.msdn.com/b/dotnet/archive/2013/09/25/immutable-collections-ready-for-prime-time.aspx