System.Collections.Immutable应该如何使用?

时间:2019-03-20 01:34:37

标签: c# .net inheritance immutability immutable-collections

我想创建一个行为类似于不可变列表的对象,并带有一些其他功能。为此,我可以实现自己的不可变列表类(在CodeReview上{I gave this a shot)。但是,似乎最好使用NuGet提供的System.Collections.Immutable。但是我对如何使用提供的结构有些困惑。

  • 我只想将ImmutableList<T>继承到我的课程中,但是对于apparently very good reasons,它是sealed

  • 我的班级可以实现IImmutableList<T>接口并提供所有必需的接口方法,但是.NET团队花费了大量时间implementing ImmutableList<T> well and efficiently,所以我没有愿望(或没关系)重新实现其功能。

  • 我可以创建一个中间的“ MyImmutableList<T>”类,该类通过IImmutableList<T>后备列表实现private ImmutableList<T>。 (对我而言)这似乎是多余的(请参见下面的想象中的MyImmutableList<T>),我不确定它会保留ImmutableList<T>的所有重要性能和内存优化,因为它只是通过了对backingList进行工作并为每个方法创建整个集合的new实例(而不是操纵节点指针),但是我不确定。

所以最后,我的问题是如何使用System.Collections.Immutable对象和接口来创建自己的对象,使其表现得像不可变的集合?用于此吗?

/// <summary>
/// An example implementation of `IImmutableList<T>` so that
/// I can create objects that behave like `ImmutableList<T>`s.
/// </summary>
class MyImmutableList<T> : IImmutableList<T>
{
    private readonly ImmutableList<T> backingList;
    public static readonly MyImmutableList<T> Empty = new MyImmutableList<T>(ImmutableList<T>.Empty);
    public int Count => this.backingList.Count;
    public T this[int i] => this.backingList[i];

    protected MyImmutableList(IEnumerable<T> values)
    {
        this.backingList = ImmutableList<T>.Empty.AddRange(values);
    }

    #region Methods I want to implement.

    public MyImmutableList<T> Clear()
    {
        return MyImmutableList<T>.Empty;
    }

    public MyImmutableList<T> Add(T value)
    {
        return new MyImmutableList<T>(this.backingList.Add(value));
    }

    public MyImmutableList<T> AddRange(IEnumerable<T> values)
    {
        return new MyImmutableList<T>(this.backingList.AddRange(values));
    }
    // ...
    // Do this for every method I want to implement.
    // ...

    public IEnumerator<T> GetEnumerator() { return this.backingList.GetEnumerator(); }
    IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); }

    #endregion

    #region Explicit interface methods. Must all be here, but shouldn't do anything?

    IImmutableList<T> IImmutableList<T>.Clear() { throw new NotSupportedException() /* or do something? */; }
    IImmutableList<T> IImmutableList<T>.Add(T value) { throw new NotSupportedException() /* or do something? */; }
    IImmutableList<T> IImmutableList<T>.AddRange(IEnumerable<T> values) { throw new NotSupportedException() /* or do something? */; }
    // ...
    // Do this for all 14 IImmutableList<T> methods
    // ...

    #endregion
}

1 个答案:

答案 0 :(得分:0)

从任何意义上继承一个收藏集都是很不正常的,我说这很不正常,但它不是完整的气味。虽然正确,但是您已经使用了该界面。

但是..

如果您需要从ImmutableList中删除功能,我可能只是从一个全新的类开始,仅添加您需要的类,实现标准接口并使用后备列表。

或者,如果您需要添加某些自定义列表功能,则扩展方法是一个不错的选择。这样,您不需要所有锅炉。

如果这都不适合您的口味,那么您在做什么就可以了。

尽管如此,对我来说可疑的是您要添加的功能,以及这是关注分离还是 SRP 问题。球员名单不是球队。

  

是否有可能从未打算将其用于此目的

什么都没有,您可以随心所欲地随意射击!

</TotallyOpinionatedAnswerOver>