Eliminating Nulls in C# with Functional Programming
Tags: functional, csharp, dotnet, codequality
Published: 2019-09-12 03:00:20

This is a short and sweet article showing how the `Option` class can bring functional programming concepts to C# codebases and prevent null reference exceptions.

This article will be using the extremely popular [language-ext](https://github.com/louthy/language-ext) library as the most popular .NET functional programming library built for object oriented languages (aside from F#).

# Installing the Language-Ext Library

In order to work with the [language-ext](https://github.com/louthy/language-ext) library, you will need to [add a NuGet reference to the package](https://www.nuget.org/packages/LanguageExt.Core). This can be done via NuGet Package Manager in Visual Studio or by running `Install-Package LanguageExt.Core` from the package manager console.

# What is an Option?

Options are a reference type that either contain *some* value or have *none*. As an example, look at the following method that searches a dictionary and returns a value from it:

```cs
public Option<ResumeKeyword> GetKeyword(
   IDictionary<string, ResumeKeyword> keywords, 
   string word) { 

  // Ensure we're searching for a lower-cased non-null word
  string key = word ?? word.ToLowerInvariant() : string.Empty;

  // If the keyword is present, return it
  if (keywords.ContainsKey(key)) {
    return keywords[key]; // Implicitly converted to Some<ResumeKeyword>
  }

  // No keyword found
  return Option<ResumeKeyword>.None;
}
```

In this method, since the return type is `Option<ResumeKeyword>`, the return type will either be of `Some<ResumeKeyword>` or `None`. The result will never explicitly be `null` so callers will never have to worry about null values.

The compiler is able to convert a standard value to a `Some` value, but the syntax of the `None` return type is less than ideal as we can start to see the added complexity of working with `Option`.

Thankfully, the return type can be simplified if we add the following using at the top of the file: `using static LanguageExt.Option<ResumeKeyword>;`

This allows us to simply `return None;` instead of doing `return Option<ResumeKeyword>.None;` which reads significantly better.

# Working with Options

Now that you have an `Option`, you want to be able to work with it. This is where the appeal of `Option` starts to come into play. Because we're working with an `Option` the compiler doesn't let us make potentially buggy code like the following:

```cs
// Give a bump for various words in the title
foreach (var word in job.Title.Split())
{
    var keyword = FindKeyword(keywordBonuses, key);
    jobScore += keyword.Value; // Does not compile
}
```

This code does not compile because `keyword` is an `Option<ResumeKeyword>` instead of a `ResumeKeyword` and so it cannot access the members of `ResumeKeyword` directly. This inconvenience is actually a good thing because we know that `FindKeyword` can sometimes not find any keyword match, which would result in a `NullReferenceException` in a standard application if we forgot to check for `null`.

Instead we write the following:

```cs
// Give a bump for various words in the title
foreach (var word in job.Title.Split())
{
    var keyword = FindKeyword(keywordBonuses, key);
    jobScore += keyword.Some(k => k.Value)
                       .None(0);
}
```

Here we're saying that we want to increase the score by the `Value` of the `ResumeKeyword` if *Some* keyword is present and, if *None* is present, score the word as 0 or filler.

The compiler's type checking will enforce these rules and make sure we arrive at the correct types, forcing us to think about whether or not the value is present and act accordingly.

For scenarios where you only want to do something if a value is present or absent and you don't need the actual value, you can check the `IsSome` or `IsNone` properties. For example:

```cs
if (keyword.IsNone) {
   Console.WriteLine($"No value defined for keyword '{word}');
}
```

# What about nullable types?

.NET has had the concept of [nullable types](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/nullable-types/) for awhile via `Nullable<T>` (often coded as `T? myVar`). 

A nullable type is a way of representing a value type as a nullable object. This is different from an Option because:

1. Options work with both reference and value types
2. While `Nullable<T>` offers `HasValue` and `Value` members, `Option<T>` offers convenience methods to react in specific ways to *Some* or *None* conditions as we saw above.

# Summary

[Language-Ext's Option<T> class](https://louthy.github.io/language-ext/LanguageExt.Core/LanguageExt/Option_A.htm) forces you to make intelligent decisions and work with potentially missing values in a safe way.

The downside of this is that it adds complexity to both reading and writing your code, but in quality critical aspects of your codebase or areas where null values are frequently possible, it might make sense to incorporate `Option<T>` into your code.

Also, bear in mind that `Option<T>` is only a slice of the capabilities offered by Language-Ext. Check out the full library to read more or follow me for notifications of future posts.

If you're curious about more ways of eliminating entire classes of defect, check out [my article on making defects impossible](https://dev.to/integerman/making-defects-impossible-16c).

{% link https://dev.to/integerman/making-defects-impossible-16c %}