NullReferenceException & LINQ XOrDefault methods
Tags: beginners, tutorial, cshap, coding
Published: 2023-08-14 05:00:00

_I originally posted an extended version of this post on [my blog](https://canro91.github.io/2023/03/20/UseOptionInsteadOfNull/) a couple of months ago. It's part of a series called "Goodbye, NullReferenceException."_

Last time, we covered when [NullReferenceException is thrown](https://dev.to/canro91/what-nullreferenceexception-is-and-how-to-avoid-it-2o35). This time, let's learn how to prevent NullReferenceException when working with LINQ `XOrDefault` methods.

If we don't check the result of LINQ `FirstOrDefault()`, `LastOrDefault()`, and `SingleOrDefault()` methods, we could get NullReferenceException.

In general, the `XOrDefault()` methods return `null` when the source collection has reference types, and there are no matching elements.

Let's focus on `FirstOrDefault()`. It finds the first element of a collection or the first element matching a condition. If the collection is empty or doesn't have matching elements, it returns the default value of the collection's type. For reference types, that's a `null`.

For example, let’s find in our catalog of movies a “perfect” film,

```csharp
var movies = new List<Movie>
{
    new Movie("Shrek", 2001, 3.95f),
    new Movie("Inside Out", 2015, 4.1f),
    new Movie("Ratatouille", 2007, 4f),
    new Movie("Toy Story", 1995, 4.1f),
    new Movie("Cloudy with a Chance of Meatballs", 2009, 3.75f)
};

// We don't have any perfect movie on our list,
// FirstOrDefault returns null
var theBest = movies.FirstOrDefault(movie => movie.Rating == 5.0);
Console.WriteLine(theBest.Name);
//                ^^^^^
// Boooom!

record Movie(string Name, int ReleaseYear, float Rating);
```

We could simply check if `theBest` is `null` before using it. But, there are other alternatives to prevent the NullReferenceException when working with `XOrDefault` methods.

## 1. XOrDefault overloads from .NET 6.0

[.NET 6.0 released some new LINQ methods and overloads](https://canro91.github.io/2022/06/27/NET6LinqMethods/). With .NET 6.0, we can pass a second parameter to the `XOrDefault()` methods as a default value if the collection is empty or there are no matching elements. Like this,

```csharp
var movies = new List<Movie>
{
    new Movie("Shrek", 2001, 3.95f),
    new Movie("Inside Out", 2015, 4.1f),
    new Movie("Ratatouille", 2007, 4f),
    new Movie("Toy Story", 1995, 4.1f),
    new Movie("Cloudy with a Chance of Meatballs", 2009, 3.75f)
};

var theBestOfAll = new Movie("My Neighbor Totoro", 1988, 5);

// With .NET 6.0 FirstOrDefault()
var theBest = movies.FirstOrDefault(
                    movie => movie.Rating == 5.0,
                    theBestOfAll);
                    // ^^^^^
Console.WriteLine(theBest.Name);  // "My Neighbor Totoro"
//                ^^^^^
// We're safe here in any case

record Movie(string Name, int ReleaseYear, float Rating);
```

Since we don't have any perfect movie in our catalog, `FirstOrDefault()` should return `null`. But, we're passing `theBestOfAll` as a custom default. We're safe to use the result of `FirstOrDefault()` without worrying about `null` and NullReferenceException.

<figure>
<img src="https://source.unsplash.com/W-ypTC6R7_k/600x400" alt="Kitty on a box" />

<figcaption>That's an Option&lt;Cat&gt;...Photo by <a href="https://unsplash.com/@jiaweizhao?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Jiawei Zhao</a> on <a href="https://unsplash.com/photos/W-ypTC6R7_k?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a></figcaption>
</figure>

## 2. Use Optional's XOrNone

Functional languages like F# or Haskell use a different approach for `null`. Instead of `null`, they use an `Option` or `Maybe` type.

With the `Option` type, we have a “box” that might have a value. It’s the same concept of nullable ints.

For example,

```csharp
int? maybeAnInt = null;

var hasValue = maybeAnInt.HasValue;
// false

var dangerousInt = maybeAnInt.Value;
//                            ^^^^^
// Nullable object must have a value.

var safeInt = maybeAnInt.GetValueOrDefault();
// 0
```

With nullable ints, we have a variable that either holds an integer or `null`. Also, we have the `HasValue` and `Value` properties and the `GetValueOrDefault()` method to access their inner value.

With the `Option` type, we extend the concept of a box with possibly a value to reference types. For example, if we write `Option<Movie> maybeNull`, we could have a movie or "nothing."

The `Option` type has two subtypes: `Some` represents a box with a value inside it, and `None`, an empty box.

### Optional library

C# doesn't have a built-in `Option` type (yet?). We have to write our own or use a third-party library. Let's bring one: the [Optional library](https://github.com/nlkl/Optional), which offers _"a robust option type for C#."_

With the Optional library, to create a box with a movie, we write `Option.Some(anyMovie)`; and to create an empty box to replace `null`, we write `Option.None<Movie>()`.

For example,

```csharp
using Optional;
//    ^^^^^

Option<Movie> someMovie = Option.Some(new Movie("Shrek", 2001, 3.95f));
Option<int> none = Option.None<Movie>();

var shrek = someMovie.Map(value => value.Name)
                     .ValueOr("Nothing");
// "Shrek"

var nothing = none.Map(value => value.Name)
                  .ValueOr("Nothing");
// "Nothing"
```

To print a movie name, we first use the `Map()` method. It opens a box, transforms its value, and return a new box with the result. We wrote `Map(value => value.Name)` to grab a movie name.

Then, we used the `ValueOr()` method. It works like the `GetValueOrDefault()` of nullable ints. If the box doesn't have a value, it returns a default value instead.

### XOrNone

The Optional library has the `FirstOrNone()`, `LastOrNone()` and `SingleOrNone()` methods instead of the usual `XOrDefault()`. When there isn't a matching element, they return `None` instead of `null`.

After that quick introduction to the `Option` type, let's use `FirstOrNone()` from the Optional library instead of `FirstOrDefault()`,

```csharp
using Optional.Collections;
//    ^^^^^

var movies = new List<Movie>
{
    new Movie("Shrek", 2001, 3.95f),
    new Movie("Inside Out", 2015, 4.1f),
    new Movie("Ratatouille", 2007, 4f),
    new Movie("Toy Story", 1995, 4.1f),
    new Movie("Cloudy with a Chance of Meatballs", 2009, 3.75f)
};

var theBestOfAll = new Movie("My Neighbor Totoro", 1988, 5);

// With Optional's FirstOrNone()
var theBest = movies.FirstOrNone(movie => movie.Rating == 5.0)
                    // ^^^^^
                    .ValueOr(theBestOfAll);
                    // ^^^^^
Console.WriteLine(theBest.Name);  // My Neighbor Totoro

record Movie(string Name, int ReleaseYear, float Rating);
```

Again, we don't have a perfect movie in our catalog, `FirstOrNone` returns `None`, an empty box. Then, with the `ValueOr()` method, we print our favorite movie.

When we use the `XOrNone()` methods, we're forced to check if they return something before using their result. We didn't have to worry about `null`.

Voilà! Those are two alternatives to prevent NullReferenceException when working with LINQ `XOrDefault()` methods: using .NET 6.0 new overloads and the Option type from Functional Languages.

If you want to learn more about LINQ, check my [Quick Guide to LINQ]({% post_url 2021-01-18-LinqGuide %}) to start learning about it. Forgetting to check for null is only one of the [most common mistakes when working with LINQ](https://canro91.github.io/2022/06/13/LinqMistakes/). 

***

_Hey! I'm Cesar, a software engineer and lifelong learner. If you want to support my work, check [my courses on Educative](https://bit.ly/imcsarag-courses). I have precisely one course about preventing NullReferenceException where we cover more techniques like the ones in this post._

_Happy coding!_