C# 持久集合和标准集合接口
我正在实现一个持久性集合——为了便于讨论,假设它是一个单链接列表,具有函数式语言中常见的样式C# 持久集合和标准集合接口,c#,.net,collections,C#,.net,Collections,我正在实现一个持久性集合——为了便于讨论,假设它是一个单链接列表,具有函数式语言中常见的样式 class MyList<T> { public T Head { get; } public MyList<T> Tail { get; } // other various stuff // . . . } 假设添加将作为一种副作用执行,从而使集合发生变异。但这是一个持久数据结构,因此Add()应该创建一个新列表并返回它 MyList<
class MyList<T>
{
public T Head { get; }
public MyList<T> Tail { get; }
// other various stuff
// . . .
}
假设添加将作为一种副作用执行,从而使集合发生变异。但这是一个持久数据结构,因此Add()应该创建一个新列表并返回它
MyList<T> Add(T item); // what we really want
MyList添加(T项);//我们真正想要的
解决这个问题的最佳方法似乎是只创建我们想要的版本,并生成接口中定义的版本的非功能性显式实现
void ICollection<T>.Add(T item) { throw new NotSupportedException(); }
public MyList<T> Add(T item) { return new MyList<T>(item, this); }
void ICollection.Add(T项){throw new NotSupportedException();}
公共MyList Add(T项){返回新的MyList(项,this);}
但我对这一选择有一些担忧:
ICollection
的IsReadOnly
的实现可能会返回true。但这似乎与Add()与类实例一起使用的其他地方暗示的内容相冲突false
,显式实现返回true
,是否以一种不易混淆的方式解决了(2)?或者这只是通过错误地暗示MyList
的Add()
方法是一个变异子而使情况变得更糟IEnumerable
派生的独立IPersistentCollection
接口我想问的是其他人对烘焙到框架中的只读(或不可变)集合的语义与实现与接口所描述行为等效的持久集合之间的紧张关系的看法,只在功能上,而不是通过变异的副作用。对我来说,创建一个新的
IPersistentList
(或者IImmutableList
,因为“持久性”听起来像是数据被保存在某个地方。)接口因为,实际上,它的行为与IList
不同。实现IList的类应该是可变的IMHO
哦,当然,我会避免使用类名List
,因为它已经是框架的一部分了
实现IList会让人困惑吗
对。尽管在某些情况下,IList
的实现会抛出(比如,当您试图调整列表大小时,但它的实现是一个数组),但我会发现,如果有一个IList
,它不能以任何方式进行变异,也不能进行快速随机访问,这会让人非常困惑
我是否应该实现一个新的IPersistentList
这取决于是否有人会使用它。您的类的消费者可能有六种不同的IPL
实现可供选择吗?我认为制作一个只由一个类实现的接口毫无意义;只要使用这个类
如果WPF的ItemsControl的ItemsSource是IList
而不是IEnumerable
,则可以获得更好的性能
但是您的持久性链表无论如何都不会有快速的随机访问。不可变性内置于
IList
的定义中-有一个IsReadOnly
属性,文档定义了在只读IList上调用mutator时应发生的情况,还有一些框架类,比如ReadOnlyCollection
@Sean U:我同意它的ME86。如果您真的想要实现IList和其他众所周知的集合接口,那么您仍然可以添加必要的成员,但是您必须在调用变异方法时抛出异常,正如您在问题中所概述的那样。是的-但是持久化且具有(相对)快速随机访问的结构呢?我希望专注于我提出的与接口相关的问题,而忽略特定类实现中出现的问题。
void ICollection<T>.Add(T item) { throw new NotSupportedException(); }
public MyList<T> Add(T item) { return new MyList<T>(item, this); }