我最近开始使用F#进行“实际工作”,并重新发现了不可变数据结构的美妙之处,例如F#中的歧视联盟和记录 . 我还发现它们很容易从C#中使用,特别是因为它们不需要对F#运行时有任何直接依赖 . 但是,在表示这些结构中的列表时,我还没有找到理想的解决方案 .
我的第一次尝试是将列表键入为seq <'a>(在C#世界中为IEnumerable),它提供了一个很好的通用集合接口,而不像ICollection <>及其朋友那样导出任何改变集合的方法 . 但是,由于我无法控制受歧视的联合或记录的构造函数,因此这些类型的实例的创建者可以提供可能在使用时更改或抛出的IEnumerable <>实现(例如LINQ表达式) . IEnumerable <>因此不会给编译器提供任何帮助,证明该值是不可变的,因此线程安全 .
我目前的策略是使用F#list类型,它确保了一个不可变的集合,但是在F#运行时添加了一个依赖项,当从非F#项目中使用它时看起来有些偏差 . 但它确实允许IEnumerable <>没有的F#模式匹配 . 它也没有在列表的实际表示中给出任何选择,并且在某些情况下(例如原始值的大列表),F#列表表示并不真正适合 .
我真正希望看到的是.NET中的不可变数组类型,表示与普通数组一样紧凑,但编译器保证不会发生变异 . 我会欢迎const在C中,尽管它可能不太可能发生 . 与此同时,我还有其他选择吗?
4 回答
如果你想要的是一个不可变的数组实现,那么你可以使用类似下面的内容
将您的普通数组包装在ReadOnlyCollection<T>实例中:
(注意,这不会复制底层集合,但会保留一个引用,并且会修改
IList<T>
等的成员以引发异常 . )我建议在immutability上查看Eric Lippert's系列,这是一个非常有用的读物 . 关于immutable queue的第4部分将是一个很好的起点 .
Microsoft发布了Immutable collections nugget包的稳定版本 . 它还没有ImmutableArray . 但是这些不可变数据结构应该非常有用 .
ImmutableList
ImmutableDictionary
ImmutableSortedDictionary
ImmutableHashSet
ImmutableSortedSet
ImmutableStack
ImmutableQueue
http://blogs.msdn.com/b/dotnet/archive/2013/09/25/immutable-collections-ready-for-prime-time.aspx