Generic lists and Predicates

Recently I was working with a generic list containing my own Favorite class. My Favorite class contains an url and a title:

using System.Collections.Generic;

public class Favorites
{
  private List<Favorite> _favoriteList = new List<Favorite>();
}

One of the functions on my list is to remove all Favorites with a specific url. I quickly jumped to the help file and found the RemoveAll() function which takes a Predicate. A predicate is a generic delegate that takes the same type as the List<> and returns true if the parameter matches a statement:

public void DinosaurExample()
{
  List<string> dinosaurs = new List<string>();

  dinosaurs.Add("Compsognathus");
  dinosaurs.Add("Amargasaurus");
  dinosaurs.Add("Oviraptor");
  dinosaurs.RemoveAll(EndsWithSaurus));
}

private static bool EndsWithSaurus(String s)
{
  if ((s.Length > 5) &&
     (s.Substring(s.Length - 6).ToLower() == "saurus"))
  {
    return true;
  }
  else
  {
    return false;
  }
}

 The EndsWithSaurus(String s) is the predicate and the function returns true if the matching string ends with “saurus”, removing “Amargasaurus” from the list.

But hey! What if I don’t have a hard-coded match in my code (I rarely have)? The predicate cannot take any parameters. Also, it’s a Static member, polluting my class.

The solution is to create a “predicate class” that takes the expression to match as a parameter:

internal class FavoriteUrlMatch
{
  private string _url;
 
  public FavoriteUrlMatch(string url)
  {
    _url = url;
  }
   
  public bool Match(Favorite fav)
  {
    return fav.Url == _url;
  }
}

Then I can invoke my FavoriteUrlMatch class from my Favorites class:

public void Delete(string url)
{
  FavoriteUrlMatch match = new FavoriteUrlMatch(url);
  _favoriteList.RemoveAll(match.Match);
}

I am not very proud of this solution, but I cannot find a better one.

Advertisement

About briancaos

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in General .NET and tagged , , . Bookmark the permalink.

5 Responses to Generic lists and Predicates

  1. Eldblom says:

    First of all, in my view predicates should be concise one-line methods – like your EndsWithSaurus method and should therefore be inline anonymous methods. Calling a internal method in a LINQ method makes the code less readable and can lead to nasty things like placing complex business logic in a LINQ query.
    Secondly, I’m not sure why your internal method needs to be static. The method this.EndsWithSaurus is not much different from match.Match in this context.

    Last but not least, ain’t the LINQ extension methods great?! :-)

    Like

  2. briancaos says:

    The solution is even simpler than I thought, as LINQ will solve my problem.

    The following code will remove all favorites where the property “Url” matches my parameter:

    public void Delete(string url)
    {
    _favoriteList.RemoveAll(x => x.Url == url);
    }

    Like

  3. Thanks. This is exactly what I was looking for!

    Like

  4. Pingback: C# Lists in Lists – Getting all inner values, or the unique inner values | Brian Pedersen's Sitecore and .NET Blog

  5. Pingback: C# List Batch – Braking an IEnumerable into batches with .NET | Brian Pedersen's Sitecore and .NET Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.