Retrieving Data From Collections/Enumerables Safely in .NET

Background

While developing any sort of application, we are almost always dealing with some sort of collection or enumerable data structure and we are almost always using LINQ to query it. It’s such a common aspect of coding that working with them has become second nature and at times it can be easy to forget best practices when using them. The most commonly forgotten best practice being the safe retrieval of data contained within them.

The Problem

Let’s say we have the following code:

var myList = new List<string>();

// Do stuff to add items to myList

var firstItem = myList.First();

var allUppercase = firstItem.ToUpper();

Console.WriteLine(allUppercase);

Do we see an issue here? What happens if myList.First(); is empty? Calling myList.First(); on an empty list will lead to an InvalidOperationException. BOOM our code is broken.

The Solution

The first aspect we need to consider is whether or not the collection will ever be empty. If you know for sure that it never will be, then calling myList.First(); isn’t a huge deal (but we should still check to see if the item it returns is null before using it).

The next aspect to consider is how you are using First(). What I mean is, if we have the following code:

var myList = new List<string> { "myItem" };

var firstItem = myList.First();

var allUppercase = firstItem.ToUpper();

Console.WriteLine(allUppercase);

calling myList.First(); isn’t a big deal because there is at least one item in the list. But what if we have the following code?

var myList = new List<string> { "myItem" };

var firstItem = myList.First(item => item == "otherItem");

var allUppercase = firstItem.ToUpper();

Console.WriteLine(allUppercase);

This is going to throw an InvalidOperationException becuase myList does not contain a string that is equal to otherItem.

So how do we solve this? Simple, we use FirstOrDefault() which will either return the first item or the default value of the type the collection/enumerable contains if the collection/enumerable is empty or there are no items matching your predicate.

var myList = new List<string>();

var firstItem = myList.FirstOrDefault();

if (firstItem != default(string))
{
	var allUppercase = firstItem.ToUpper();

	Console.WriteLine(allUppercase);
}

The above code covers both cases we’ve described in the problem safely! If myList is empty, we receive the default value of string (which is null). If we were to pass the same predicate in the previous example where we are looking for the first string that matches otherString, then again, we will receive the default value of string. We then check to see if we received the default value, and if not, we know we have a value and we can do something with it 🙂

TL;DR

When using collections and enumerables in .NET we should take the following steps:

  • First, determine if the collection/enumerable could ever be empty. If so, use FirstOrDefault().
  • Next, determine if the collection will ALWAYS have at least one member. If not, use FirstOrDefault().
  • Next, if you are using a predicate to filter the collection/enumerable, determine if your predicate would have the potential to not find a match. If so, use FirstOrDefault(predicateHere).
  • If the collection/enumerable will NEVER be empty and will ALWAYS have at least one value, and if you are using a predicate, will ALWAYS match the predicate you are using, then you can use First() (but you should always ALWAYS check if the item is equal to it’s default value. E.g. if(firstItem == default(string)){ }). But… I would still probably use FirstOrDefault() anyway (unless you really want that tiny micro-optimization of First()).

Checkout my GitHub: https://github.com/StephenMP

Leave a comment