Как System.Collections.Immutable предназначен для использования? - PullRequest
0 голосов
/ 20 марта 2019

Я хотел бы создать объект, который ведет себя как неизменный список, с некоторыми дополнительными функциями. Чтобы сделать это, я мог бы реализовать свой собственный класс неизменяемого списка, который делает это ( Я дал этому снимку в CodeReview). Тем не менее, кажется предпочтительным и более естественным использовать поставляемую System.Collections.Immutable от NuGet. Но я немного запутался в том, как использовать предоставленные структуры.

  • Я хотел бы просто унаследовать ImmutableList<T> от моего класса, но это sealed для очевидно очень веских причин .

  • Мой класс мог бы реализовать интерфейс IImmutableList<T> и предоставить все необходимые методы интерфейса, однако команда .NET потратила много времени , хорошо и эффективно внедряя ImmutableList<T> , поэтому у меня есть нет желания (или навыка в этом отношении) повторно реализовать его функциональность.

  • Я мог бы создать промежуточный класс "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 голосов
/ 20 марта 2019

Необычно наследовать от коллекции в любом смысле, я говорю необычно, но это не полный запах.Хотя вы правильно использовали интерфейс.

Однако ..

Если вам нужно удалить функциональность из ImmutableList, я, вероятно, просто начну с совершенно нового класса и добавлю только то, что вам нужно, реализуйте стандартные интерфейсы и используйтесписок поддержки.

Или, если вам нужно добавить определенные пользовательские функции list'y, хорошим кандидатом будут методы расширения.Таким образом, вам не нужно все покрытие котла.

Если ничего из этого не устраивает, то, что вы делаете, хорошо.

Хотя для меня подозрительным является добавляемая вами функциональность и является ли это Разделением проблем или SRP , например, проблема.Список игроков не является командным действием.

Возможно ли, что оно никогда не предназначалось для этого

Ничто не предназначено, вы можете в любой момент выстрелить себе в ногу!

</TotallyOpinionatedAnswerOver>

...