System.InvalidOperationException: Sequence contains no elements

Problem

When you call .First() on an empty IEnumerable, you get the following exception:

System.InvalidOperationException: Sequence contains no elements

Solution

Option 1 – Use .FirstOrDefault() instead of .First()

When the IEnumerable is empty, .FirstOrDefault() returns the default value for the type.

IEnumerable<IMessage> data = GetData(); var first = data.FirstOrDefault(); Console.WriteLine($"First = {first == default(IMessage)}");

For reference types this returns null. For value types this returns 0 or that type’s equivalent of 0.

Option 2 – Use .Any() to check if the IEnumerable is empty

Instead of dealing with the default value (which is either null or 0), you can use .Any() to check if the IEnumerable is empty.

IEnumerable<IMessage> data = GetData(); if(data.Any()) { var first = data.First(); Console.WriteLine($"First = {first}"); } else { Console.WriteLine("There's no data"); }

Option 3 – Get your own default object from .FirstOrDefault()

Create an extension method that returns a default object you specify.

static class IEnumerableExtension { public static T FirstOrDefault<T>(this IEnumerable<T> list, T defaultObj) { if (!list.Any()) return defaultObj; else return list.First(); } }

With reference types you can use the Null Object pattern (an object that does nothing). The benefit of this you don’t need to deal with null checking. In my case, I’m setting the default to EmptyMessage.

IEnumerable<IMessage> data = GetData(); var first = data.FirstOrDefault(new EmptyMessage());

With value types you can specify a value that has special meaning in your system.

IEnumerable<int> intData = GetIntData(); var firstInt = intData.FirstOrDefault(-1);

Leave a Comment