在 .NET 中表示不可变列表的最佳方式是什么?
我最近开始使用 F# 进行“实际工作”,并重新发现了不可变数据结构的美妙之处,例如 F# 中的可区分联合和记录。我还发现它们在 C# 中使用起来非常简单,特别是因为它们不需要对 F# 运行时有任何直接依赖。然而,当涉及到在这些结构中表示列表时,我还没有找到理想的解决方案。
我的第一次尝试是将列表输入为 seq<'a> (C# 世界中的 IEnumerable)提供了一个很好的通用集合接口,无需导出任何用于以 ICollection<> 方式改变集合的方法。它的朋友们也这样做。但是,由于我无法控制有区别的联合或记录的构造函数,因此这些类型的实例的创建者可以提供 IEnumerable<> 类型。使用时可能会更改或抛出异常的实现(例如 LINQ 表达式)。 IEnumerable<>因此,编译器不会给我任何帮助来证明该值是不可变的,因此是线程安全的。
我当前的策略是使用 F# 列表类型,它确实保证了不可变集合,但增加了对 F# 运行时的依赖,并且在非 F# 项目中使用时看起来有点不对劲。然而,它确实允许 IEnumerable<> 进行 F# 模式匹配。没有。它也没有在列表的实际表示中提供任何选择,并且在某些情况下(例如原始值的大型列表)F# 列表表示并不真正适合。
我真正希望看到的是 .NET 中的不可变数组类型,其表示方式与普通数组一样紧凑,但编译器保证不会发生变化。我会像 C++ 中那样欢迎 const,尽管这不太可能发生。与此同时,我还错过了其他选择吗?
I've recently started using F# for "real work" and rediscovered the beauty of immutable data structures such as the discriminated unions and records in F#. I've also found them to be quite straight forward to use from C#, especially as they don't require any direct dependencies on the F# runtime. However, when it comes to representing lists in these structures, I have not yet found an ideal solution.
My first attempt was to type the lists as seq<'a> (IEnumerable in the C# world) which provides a nice general collection interface without exporting any methods for mutating the collection the way ICollection<> and its friends does. However, since I have no control over the constructor of a discriminated union or record, it is possible for the creator of an instance of these types to provide an IEnumerable<> implementation that might change or throw when used (such as a LINQ expression). IEnumerable<> will therefor not give me any help from the compiler in proving that the value is immutable and therefor thread safe.
My current strategy is to use the F# list type which does guarantee an immutable collection, but adds a dependency on the F# runtime and looks a bit off when used from non F# projects. It does however allow for F# pattern matching which IEnumerable<> does not. It also doesn't give any choice in the actual representation of a list, and in some cases (such as large lists of primitive values) the F# list representation does not really fit.
What I really would like to see is an immutable array type in .NET, represented just as compactly as the normal array but with a compiler guarantee of not being mutated. I would welcome const as in C++ although it's probably not very likely to happen. In the meantime, is there any other option I've missed?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果你想要的是一个不可变的数组实现,那么你可以使用类似下面的东西
If what you want is an immutable array implementation then you can just use something like the following
将普通数组包装在
ReadOnlyCollection
< /a> 实例:(注意,这不会复制底层集合,而是保存一个引用,并且修改
IList
等的成员会抛出异常。)Wrap your normal array in a
ReadOnlyCollection<T>
instance:(Note, this does not copy the underlying collection, but holds a reference and and modifying members of
IList<T>
etc. are implemented to throw an exception.)Microsoft 发布了不可变集合块包的稳定版本。它不附带 ImmutableArray 还没有。但这些不可变的数据结构应该非常有用。
http://blogs.msdn.com/b/dotnet/archive/2013/09/25/immutable-collections-ready-for-prime-time.aspx
Microsoft releases a stable version of Immutable collections nugget package. It doesn't come with ImmutableArray yet. But these immutable data structures should be very useful.
http://blogs.msdn.com/b/dotnet/archive/2013/09/25/immutable-collections-ready-for-prime-time.aspx
我建议查看 Eric Lippert 的 系列 不变性,这是一本非常有用的读物。第 4 部分:关于 不可变队列将是一个很好的起点。
I'd recommend looking at Eric Lippert's series on immutability, it's a very useful read. Part 4 about a immutable queue would be a good place to start.