Setting a Default for FirstOrDefault

Tags: Linq, C#

The linq expression FirstOrDefault is nifty if you are trying to get the First value in a sequence and you don't want a pesky InvalidOperationException if there are no elements returned.  

		
objects = new Band[] {};
first = objects.FirstOrDefault(); // returns null
first = objects.First(); // returns InvalidOperationException

If you want FirstOrDefault to have a different default value other than null you can use DefaultIfEmpty.

		
objects = new Band[] {};
first = objects.DefaultIfEmpty(new Band { Name = "Black Sabbath" }).FirstOrDefault();  // returns "Black Sabbath"
first = objects.DefaultIfEmpty(new Band { Name = "Black Sabbath" }).First(); // also returns "Black Sabbath"

It's Not Empty

This is handy but ONLY if your sequence is empty. What if you want a default when you have a predicate that returns no elements. Can I do this and get my default "Black Sabbath" band?

	
objects = new Band[] { new Band { Name = "Iron Maiden" } };
first = objects.DefaultIfEmpty(new Band { Name = "Black Sabbath" }).FirstOrDefault(o => o.Name == "Slayer");  // returns null

No.  This returns null.  DefaultIfEmpty doesn't do anything since my objects array is not empty. Actually linq has no way to change the default value of FirstOrDefault.  It can only use the default object value, null, or default integer value, 0, etc.

A Linq Solution

If we really want to achieve a different default using only linq we could do something a bit convoluted like this:

		first = objects.Where(o => o.Name == "Slayer").DefaultIfEmpty(new Band { Name = "Black Sabbath" }).FirstOrDefault();   // returns "Black Sabbath" 

Another Way

Here's another workaround that just uses the Null coalescing operator.

		
first = objects.FirstOrDefault(o => o.Name == "Slayer") ?? new Band { Name = "Black Sabbath" };  // returns "Black Sabbath" 

This works and is a tiny bit more compact.  

No Comments

Add a Comment