简体   繁体   中英

How To Create An Extension Method In C# Using A Predicate

I'm trying to create an extension method called RemoveWhere that removes an item from a List collection based on a predicate. For example

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

I'm using Microsoft's Where extension method signature as a starting point. Here's what I have so far:

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???

}

I don't know how to use the predicate. Can someone help me finish this? Thank you!

There is already a method in list that does that try. Predicate should be a Predicate then you can use source.RemoveAll(predicate)

The Predicate parameter should be: 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;
}

EDIT: As others have pointed out, this method is either misnamed, or it already exists on List. My guess is just that you're trying to understand how a passed in delegate is used by the method itself. For that you can look at my sample. If that is not your intent, I'll delete this answer as the code really is kind of pointless.

As others have pointed out, List<T>.RemoveAll will do what you want. If however, this is a learning experience or you want to operate on any IList<T> (which doesn't have RemoveAll ) this should do the same as RemoveAll but as an extension method.

public static void RemoveWhere<T>(this IList<T> source, Func<T, bool> predicate)
{
  //exceptions here...

  // how to use predicate here???
  for(int c = source.Count-1 ; c >= 0 ; c--)
  {
    if(predicate(source[c]))
    {
      source.RemoveAt(c);
    }
  }
}

As boca observed, List<T> already has a method to do this. A somewhat larger issue, though, is that this really isn't a scenario where you should be creating a new extension method. There's already an extension method that takes a predicate: Where .

Granted, doing this:

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

is a little more code than using RemoveAll :

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

But:

  • it also builds a new list instead of modifying the existing list in place,
  • list can actually be any IEnumerable<T> , not just a List<T> ,
  • the Where method is a commonly used, well-documented extension method that any reasonably-skilled C# programmer can be expected to recognize on sight
  • it's clear to anyone reading that code that it's creating a new list, and
  • if you don't want to create a new list, just leave off ToList() and enumerate over result .

It's really hard for me to envision circumstances where I'd want to write an extension method for IEnumerable<T> that takes a predicate. You're saving very little by making it possible for you to not use Where() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM