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);}
但我对这一选择有一些担忧:

  • 这会让用户感到困惑吗?我设想了这样的场景:有人在处理这个类,发现对它调用Add()有时会引发异常,有时会运行,但不会像通常对ICollection所期望的那样修改列表,这取决于与所使用的引用关联的类型信息

  • 在(1)之后,
    ICollection
    IsReadOnly
    的实现可能会返回true。但这似乎与Add()与类实例一起使用的其他地方暗示的内容相冲突

  • 通过再次遵循显式实现模式,新版本返回
    false
    ,显式实现返回
    true
    ,是否以一种不易混淆的方式解决了(2)?或者这只是通过错误地暗示
    MyList
    Add()
    方法是一个变异子而使情况变得更糟

  • 还是最好忘记尝试使用现有接口,而只创建一个从
    IEnumerable
    派生的独立
    IPersistentCollection
    接口

  • edit我更改了类的名称,并切换到使用ICollection。我想重点关注对象的行为以及它与接口的关系。我只是举了一个简单的例子。我很欣赏这样的建议:如果我要实现一个cons列表,我应该尝试用一个不太容易混淆的名称,并且应该避免实现IList,因为该接口是用于快速随机访问的,但它们是一些无关紧要的问题


    我想问的是其他人对烘焙到框架中的只读(或不可变)集合的语义与实现与接口所描述行为等效的持久集合之间的紧张关系的看法,只在功能上,而不是通过变异的副作用。

    对我来说,创建一个新的
    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); }