Feed on
Posts
Comments

The FirstOrDefault method built-in to the .NET libraries is perfect for returning value type defaults.  If there is a match for the condition, you get the first match, otherwise you get the default for the type.

 

 var stockCounts = new List<int> { 44, 55, 66 };
 var lowCount = 100;
 lowCount = stockCounts.FirstOrDefault(x => x < 10); // lowCount == 0

This works great for value types, in the example above you get back zero if there is no match for the predicate (x<10).

For reference types, you get back a null reference if there is no match.  Many times, that is exactly the behavior you are looking for. But occasionally, you might want to get back a new object, not a null when the condition fails.  In other words, you’d like a factory method.

The Extension Method

Here is a simple example of a FirstOrNew factory method.

public static class EnumerableExtensions {
  public static T FirstOrNew<T>(this IEnumerable<T> item, 
                                Func<T, bool> predicate) where T : class, new() {

    var temp = item.FirstOrDefault(predicate) ?? new T();
    return temp;
  }

And here’s how to use it in your code.

var parts = new List<Part>{new Part{PartName="hammer", StockCount= 66},
                           new Part{PartName="drill", StockCount= 77}};

 Part lowStockPart = null;
// using the built-in FirstOrDefaut
 lowStockPart = parts.FirstOrDefault(x => x.StockCount < 10); 
 // lowStockPart == null 
 
 
 lowStockPart = parts.FirstOrNew(x => x.StockCount < 20); 
 // lowStockPart != null
 
// ================
 
public class Part {
   public string PartName { get; set; }
   public int StockCount { get; set; }
 }

========

3 Responses to “FirstOrNew Extension Method for LINQ”

  1. Omer Mor says:

    Falsely This extension will return a new instance if the predicate will find you a null in your enumerable.
    You can implement a correct version with an iterator block.

  2. Omer Mor says:

    This extension will falsely return a new instance if the predicate will find you a null in your enumerable. You can implement a correct version with an iterator block.

  3. Steve Hansen says:

    This is an awesome idea, it reminds me of the ConcurrentDictionary GetOrAdd method, which I absolutely love.

    public static T FirstOrNew(this IEnumerable item,
    Func predicate, Func valueFactory) where T : class {

    return item.FirstOrDefault(predicate) ?? valueFactory();
    }

    Would also be really useful if a default constructor isn’t available or expensive :)