Является ли IEnumerable <T>Заменить плохой дизайн? - PullRequest
3 голосов
/ 13 октября 2011

Я создал следующие методы расширения.Это плохой дизайн?Должен ли я сделать это для ICollection вместо этого?

public static IEnumerable<TSource> Replace<TSource>(this IEnumerable<TSource> source, IEnumerable<TSource> newItems)
{
    return source.Except(newItems).Union(newItems);
}

public static IEnumerable<TSource> Replace<TSource>(this IEnumerable<TSource> source, IEnumerable<TSource> newItems, IEqualityComparer<TSource> comparer)
{
    return source.Except(newItems, comparer).Union(newItems, comparer);
}

Обновление: я думаю, что наименование немного неправильноЯ хочу, чтобы эта функция была Добавить с перезаписью .Обновление: добавлен компаратор в Union.

Ответы [ 2 ]

2 голосов
/ 13 октября 2011

Упрощенная логическая операция, которую вы выполняете:

 return newItems.Union(source);
 return newItems.Union(source, comparer);

Когда вы берете source.Except(newItems).Union(newItems), вы берете все отдельные элементы в source, кроме любого элемента в newItems, а затем добавляете всеотдельные элементы в newItems.Вот что делает Union!Возьмите все отдельные элементы из newItems и добавьте к ним отдельные элементы из source, которые еще не существуют.

Вы можете назвать его другим именем AddWithOverwrite, AddWithReplace и т. Д., И эти имена будут неправильными (ничего не добавляется ни к источнику, ни к исходным, ни к новым элементамизменяются каким-либо образом), но сама операция не должна быть такой сложной, как это делает ваш код.

Есть компромиссы.При подходе выше все newItems будут предшествовать source.Счетчик в том, что вы уже потеряли заказ с замененными предметами.

0 голосов
/ 13 октября 2011

номер

Если вы посмотрите на оригинальные методы расширения в LINQ, все они используют IEnumerable<T> интерфейс. Если вы используете общие коллекции, этого должно быть достаточно. Однако ваш метод Replace пропускает параметр для заменяемых элементов. Вы должны сделать что-то вроде этого:

public static IEnumerable<TSource> Replace<TSource>(this IEnumerable<TSource> source, IEnumerable<TSource> oldItems, IEnumerable<TSource> newItems)
{
    return source.Except(oldItems).Union(newItems);
}


public static IEnumerable<TSource> Replace<TSource>(this IEnumerable<TSource> source, IEnumerable<TSource> oldItems, IEnumerable<TSource> newItems, IEqualityComparer<TSource> comparer)
{
    return source.Except(oldItems, comparer).Union(newItems);
}

Обновление

Вот метод OverWrite, который я мог бы придумать:

    public static IEnumerable<TSource> OverWrite<TSource, TSelectItem>(this IEnumerable<TSource> source, IEnumerable<TSource> newItems, Func<TSource, TSelectItem> selectProperty) where TSource : class
    {
        IEnumerable<TSource> result = source;

        if (newItems != null)
        {
            result = source.Select(s => newItems.FirstOrDefault(n => EqualityComparer<TSelectItem>.Default.Equals(selectProperty(s), selectProperty(n))) ?? s);
        }

        return result;
    }

    public static IEnumerable<TSource> OverWrite<TSource, TSelectItem>(this IEnumerable<TSource> source, IEnumerable<TSource> newItems, Func<TSource, TSelectItem> selectProperty,IEqualityComparer<TSelectItem> propertyComparer) where TSource : class
    {
        IEnumerable<TSource> result = source;

        if (newItems != null)
        {
            result = source.Select(s => newItems.FirstOrDefault(n => propertyComparer.Equals(selectProperty(s), selectProperty(n))) ?? s);
        }

        return result;
    }

Вы можете использовать это так:

someObjects.OverWrite(newObjects, item => item.ID);
someObjects.OverWrite(newObjects, item => item.ID, new PropertyComparer());
...