Scala in the key of C#: Option
Update: Since I first released
Option, I've realized that it implementing IEnumerable was unneccesary to use LINQ syntax and actually made it less useful. I've updated the post to reflect these changes to
Currently reading Daniel Westheide's excellent "Neophyte's guide Scala" series and it's inspired me to port some concepts from Scala to C#. This is less about trying to replace Scala -- it has too many compelling aspects that cannot be mimicked -- and more about exploring concepts I come across in Scala in the realm i'm best versed in, and, hopefully, along the way, create some useful C# utilities. First up, the
Get thee behind me, null
Reading The Option Type the simplicity and elegance struck me. My
Option<T> is inspired by Scala's
Option[A], which in turn has its origin in Haskell's Option. On the surface it's a pretty simple container for a value that may or may not exist.
var some = Option<string>.Some("foo");
// manually checking for defined
Console.WriteLine(some.IsDefined ? some.Value : "not defined");
// => "foo"
// or use the built in helper
// => "foo"
// None is a singleton
var none = Option<string>.None;
// => "not defined"
NullReferenceException, so Option makes reference types behave more like nullable value types. But with the null coalescing operator
??, trying to check for null and substituting an alternative value is already very simple in .NET, so why bother with an Option port? After all, the most compelling usage of Option in scala, pattern matching, just cannot be reproduced in .NET, so there goes a large part of the motivation. But once I learned that
Option[A] behaves like an
Iterable and therefore could use all the common collection methods, I was intrigued.
The Power of LINQ compels you
You see, an Option is can be considered a collection of zero or one values. By implementing the
Where Extension Methods for Option we can use LINQ to chain calls together. This makes
Option much more composable than manual null checks.
Each method returns an
Option, for which the compiler insert the appropriate extension method for the specific LINQ syntax. An undefined
Option behaves just like and empty
IEnumerable, i.e. the selector callback is skipped and the query is short circuited. Using the from
x in a syntax uses
SelectMany (if there is more than one
from clause) and could just as easily have been written by manually chaining the calls:
What Else can Option do for Me?
Option implements equality comparison based on the contained type, so two Options of the same type containing the same value will be equal, according to that type's rules. Along with that
Option<T>.None equals null and all
None regardless of type have the same hashcode, i.e. 0.
Finally, in addition to
GetOrElse, there is also
OrElse, which provides a way to substitute a different
Option, allowing the chaining of many calls to get the first one that returns a value.
Option is available on github under the MIT license in the Scando repository. This repository is where I plan to put all code inspired by Scala. There's already an implementation of the
Try type in there as well, which I will be writing about shortly.