Неизменяемая вставка альтернатива - PullRequest
0 голосов
/ 23 сентября 2018

Я ищу неизменную альтернативу стандартному методу Collection<T>.Insert(Int32, T).

В моем конкретном случае у меня есть такой метод:

IEnumerable<int> Foo(IEnumerable<int> parameter, int index)
{
    var copiedParameter = new List<int>(parameter);
    copiedParameter.Insert(index, 42);
    return copiedParameter;
}

Это, очевидно, довольно утомительнои неэффективно.Мне нужно что-то вроде этого:

IEnumerable<int> Foo(IEnumerable<int> parameter, int index) => parameter.InsertImmutable(index, 42);

Конечно, я мог бы написать такой метод расширения:

public static IEnumerable<T> InsertImmutable<T>(this IEnumerable<T> collection, int index, T value)
{
    var copiedCollection = new List<T>(collection);
    copiedCollection.Insert(index, value);
    return copiedCollection;
}

Но это, очевидно, не очень улучшает ситуацию, простоперемещает проблему в другое место.

Единственный другой способ сделать это, о котором я мог подумать, это что-то вроде этого:

public static IEnumerable<T> InsertImmutable<T>(this IEnumerable<T> collection, int index, T value)
{
    var i = 0;
    foreach (var item in collection)
    {
        if (i == index)
            yield return value;
        yield return item;

        i++;
    }
}

Однако, это повторяет IEnumerable, который еще разможет снизить эффективность.

Есть ли лучший, ленивый и неизменный способ сделать это?

1 Ответ

0 голосов
/ 24 сентября 2018

На самом деле решение уже почти в вопросе, поскольку комментарии намекали мне на это.Следующий код решает мою проблему довольно хорошо:

private static IEnumerable<T> InsertImmutable<T>(this IEnumerable<T> collection, int index, T value)
{
    var i = 0;
    var inserted = false;
    foreach (var item in collection)
    {
        if (i == index)
        {
            inserted = true;
            yield return value;
        }

        yield return item;

        i++;
    }

    if (!inserted)
        yield return value;
}
...