Как создать метод расширения в C # с использованием предиката - PullRequest
1 голос
/ 22 июня 2011

Я пытаюсь создать метод расширения с именем RemoveWhere, который удаляет элемент из коллекции List на основе предиката. Например

var result = products.RemoveWhere (p => p.ID == 5);

Я использую подпись метода расширения Microsoft в качестве отправной точки. Вот что у меня есть:

public static List<T> RemoveWhere<T>(this List<T> source, Func<T, List<T>> predicate)
{
    if (source == null)
    {
        throw new ArgumentNullException("source", "The sequence is null and contains no elements.");
    }

    if (predicate == null)
    {
        throw new ArgumentNullException("predicate", "The predicate function is null and cannot be executed.");
    }

    // how to use predicate here???

}

Я не знаю, как использовать предикат. Может кто-нибудь помочь мне закончить это? Спасибо!

Ответы [ 4 ]

6 голосов
/ 22 июня 2011

В списке уже есть метод, который пытается это сделать. Предикат должен быть Предикатом, тогда вы можете использовать source.RemoveAll (предикат)

4 голосов
/ 22 июня 2011

Параметр предиката должен быть: Func<T,bool>

public static List<T> RemoveWhere<T>(this List<T> source, Func<T, bool > predicate)
{
    if (source == null)
    {
        throw new ArgumentNullException("source", "The sequence is null and contains no elements.");
    }

    if (predicate == null)
    {
        throw new ArgumentNullException("predicate", "The predicate function is null and cannot be executed.");
    }

    // how to use predicate here???
    var result = new List<T>();
    foreach(var item in source)
    {
        if(!predicate(item))
        {
            result.Add(item);
        }
    }

    return result;
}

РЕДАКТИРОВАТЬ: Как уже отмечали другие, этот метод либо неправильно назван, либо он уже существует в списке. Я предполагаю, что вы пытаетесь понять, как передаваемый делегат используется самим методом. Для этого вы можете посмотреть на мой образец. Если это не ваше намерение, я удалю этот ответ, так как код на самом деле бессмыслен.

2 голосов
/ 22 июня 2011

Как уже отмечали другие, List<T>.RemoveAll будет делать то, что вы хотите.Однако, если это опыт обучения или вы хотите работать с любым IList<T> (у которого нет RemoveAll), это должно быть то же самое, что и RemoveAll, но как метод расширения.

0 голосов
/ 22 июня 2011

Как заметил Бока, у List<T> уже есть способ сделать это.Однако более серьезная проблема заключается в том, что в действительности это не тот сценарий, в котором вам следует создавать новый метод расширения.Уже есть метод расширения, который принимает предикат: Where.

Конечно, сделав это:

var result = list.Where(x => x != 5).ToList();

немного больше кода, чем использование RemoveAll:

list.RemoveAll(x => x == 5);

Но:

  • он также строит новый список вместо изменения существующего списка на месте,
  • list может фактически быть любым IEnumerable<T>, а не простоList<T>,
  • метод Where является широко используемым, хорошо документированным методом расширения, который любой опытный программист на C # может распознать на виду
  • , который понятен любому читающемутот код, который создает новый список, и
  • , если вы не хотите создать новый список, просто пропустите ToList() и перечислите по result.

Мне действительно трудно представить себе обстоятельства, когда я хотел бы написать метод расширения для IEnumerable<T>, который принимает предикат.Вы экономите очень мало, позволяя вам не использовать Where().

...