Intro
In the projects I’ve been working on since .NET generics came out, I’ve done a lot of work with generic Lists. They are a great way to store, retrieve and generally work with objects. Most of the methods in the generic List class take as arguments either a Predicate, a Func or an Action. That can be confusing at first. This article looks to dispel that confusion and make your code more elegant by using lambda expressions for all three of these types of arguments.
For a primer on lambda expressions, see this Microsoft post:
http://msdn.microsoft.com/en-us/library/bb397687.aspx
These are quick definitions of the three classes that are covered in the article:
- Predicate - delegate that takes parameter(s), runs code using the parameter(s) and always returns a Boolean
- Func - delegate that takes parameter(s), runs code using the parameter(s) and returns the type that you specify
- Action - delegate that takes parameter(s), runs code using the parameter(s) and doesn’t return anything
So for the generic List, these arguments allow the coder to execute a method for each of the items in the generic List.
Common Code
The examples in this article will use the same common code. The following is the business entity:
public class InventoryItem
{
public int ID { get; set; }
public int NumberInStock { get; set; }
public double UnitCost { get; set; }
}
This is the list member variable that is used:
private List<InventoryItem> _inventoryList = new List<InventoryItem>();
This is what’s in the _inventoryList:

List Methods With a Predicate Argument
The generic List class Find method is an example of a method that takes a Predicate as an argument. To build up to the Predicate class, let’s first look at how finds have been typically done. For me, the foreach method was my best friend whether I used a generic List, ArrayList or whatever other data structure. Here is an example:
public InventoryItem FindInventoryForeach(int inventoryID)
{
foreach (InventoryItem item in _inventoryList)
{
if (item.ID == inventoryID)
return item;
}
return null;
}
Now, there is a better way to do this common task. The generic List class has this built in with the Find method. The argument to the Find method is the Predicate class. Remember the quick definition of a Predicate: “a delegate that takes parameter(s), runs code using the parameter(s) and always returns a Boolean”. In C#, an inline delegate creates an anonymous method and it can be assigned to a Predicate variable. This Predicate variable can then be passed into the Find method as follows:
public InventoryItem FindInventoryPredicateDelegate(int inventoryID)
{
Predicate<InventoryItem> pred = delegate(InventoryItem item)
{
return item.ID == inventoryID;
};
return _inventoryList.Find(pred);
}
This can be useful if you want to store the delegate for reuse. Of course the delegate can simply be passed into the Find method as follows:
public InventoryItem FindInventoryDelegate(int inventoryID)
{
return _inventoryList.Find(delegate(InventoryItem item)
{
return item.ID == inventoryID;
});
}
Lambda expressions simplify the preceding code. First, here is the Predicate example with a lambda expression on the right side of the ‘=’:
public InventoryItem FindInventoryPredicateLambda(int inventoryID)
{
Predicate<InventoryItem> pred = item => item.ID == inventoryID;
return _inventoryList.Find(pred);
}
The lambda expression can be read “item goes to Item.ID == inventoryID”. In other words, item is the parameter to what’s on the right of the “=>”. Again the Predicate variable can be stored for reuse. Using lambda expressions looks cleaner in my opinion. To further simplify, the Predicate variable can be bypassed in favor of using the lambda expression directly in the Find method as follows:
public InventoryItem FindInventory(int inventoryID)
{
return _inventoryList.Find(item => item.ID == inventoryID);
}
Notes about the lambda expression:
- The left side represents the parameters into the function to be evaluated, in this case, of type InventoryItem
- The right side is a boolean expression which will evaluate to true when the Find method finds the item with ‘inventoryID’
- If the item is not found, the FindInventory method will return null
- Some claim this is more difficult to learn and therefore harder for maintenance but I believe it’s cleaner (if maintenance is a concern, comment these sections of code to help the other developers learn)
The preceding Find examples all output the same with an inventoryID of 5 as shown:

The following generic List methods that have a Predicate argument are also useful:
- FindAll - returns a List of objects that meet the condition
- RemoveAll - removes the objects that meet the condition
- Exists - does the object exist that meets the condition?
- FindLast - returns the last object that meets the condition
- For the full list, see http://msdn.microsoft.com/en-us/library/s6hkc2c4.aspx
List Methods With a Func Argument
There are many List methods that take a Func type as an argument. Remember the quick definition of a Func: “a delegate that takes parameter(s), runs code using the parameter(s) and returns the type that you specify”. Func is more flexible than Predicate as it can return any type, not just bool. It depends on the List method as to the signature of the Func. Some take one argument, others more.
One of the more useful List methods is actually an extension method on Enumerable called Where. Think of the SQL WHERE clause when using this method. It allows you to get a subset of the List given the Where Func that is specified. The following is an example of this using delegates:
public List<InventoryItem> FindItemsWhereLessThanCostFuncDelegate(double unitCost)
{
Func<InventoryItem, bool> whereFunc = delegate(InventoryItem item)
{
return item.UnitCost < unitCost;
};
return _inventoryList.Where(whereFunc).ToList<InventoryItem>();
}
Note that to return a List of InventoryItem’s, you must call ToList since Where returns an IEnumerable and the query isn’t executed until the result is enumerated.
The preceding example can be simplified by using a Lambda expression:
public List<InventoryItem> FindItemsWhereLessThanCostFuncLambda(double unitCost)
{
Func<InventoryItem, bool> whereFunc = item => item.UnitCost < unitCost;
return _inventoryList.Where(whereFunc).ToList<InventoryItem>();
}
Again this would be done mainly for reusing the Func in other places of the code.
The best simplification is done by simply passing a lambda expression directly into the Where method as follows:
public List<InventoryItem> FindItemsWhereLessThanCost(double unitCost)
{
return _inventoryList.Where(item => item.UnitCost < unitCost)
.ToList<InventoryItem>();
}
The preceding Where examples all output the same with a unitCost parameter value of 2.0:
The following generic List methods that have a Func argument are also useful:
- FirstOrDefault - returns the first item that meets the condition or a default value (for an object, the default value is null)
- LastOrDefault - returns the last item that meets the condition or a default value (for an object, the default value is null)
- First - returns the first item that meets the condition
- For the full list see http://msdn.microsoft.com/en-us/library/s6hkc2c4.aspx
List Methods With an Action Argument
Remember the quick definition of an Action: “a delegate that takes parameter(s), runs code using the parameter(s) and doesn’t return anything”. There is one method in the generic List class that takes an Action argument, it is the ForEach method. All it does is run the code you specify for each of the items in the List.
In the following example, the unit cost is set to the same value for each inventory item (a separate Action variable can also be created using a delegate or lambda expression and then passed into the ForEach method):
public void UnifyUnitCost(double unitCost)
{
_inventoryList.ForEach(item => item.UnitCost = unitCost);
}
This produces the following results:

Of course I generated the output using the ForEach command as well:
helper.InventoryList.ForEach(item => Console.WriteLine(
"item ID={0}, unit cost = {1}",
item.ID.ToString(), item.UnitCost.ToString("C")));
Conclusion
The generic List class and it’s extensions have some very powerful methods to help you do common tasks. Many of them take either a Predicate, Func or Action argument. The most compact and elegant way to use methods of this type is to pass in lambda expressions, an important part of LINQ.
For a much more thorough understanding of all that LINQ has to offer, check out the Intertech class “Complete LINQ for .NET 4.0 Training”.