Optional return in C#.Net

C#.NetNullableOptional

C# Problem Overview


Java 1.8 is receiving the Optional<T> class, that allows us to explicitly say when a method may return a null value and "force" its consumer to verify if it is not null (isPresent()) before using it.

I see C# has Nullable<T>, that does something similar, but with basic types. It seems to be used for DB queries, to distinguish when a value exists and is 0 from when it doesn't exist and is null.

But it seems that C#'s Nullable<T>doesn't work for objects, only for basic types, while Java's Optional<T> only works for objects and not for basic types.

Is there a Nullable/Optional class in C#, that forces us to test if object exists before extracting and using it?

C# Solutions


Solution 1 - C#

Not in the language, no, but you can make your own:

public struct Optional<T>
{
    public bool HasValue { get; private set; }
    private T value;
    public T Value
    {
        get
        {
            if (HasValue)
                return value;
            else
                throw new InvalidOperationException();
        }
    }

    public Optional(T value)
    {
        this.value = value;
        HasValue = true;
    }

    public static explicit operator T(Optional<T> optional)
    {
        return optional.Value;
    }
    public static implicit operator Optional<T>(T value)
    {
        return new Optional<T>(value);
    }

    public override bool Equals(object obj)
    {
        if (obj is Optional<T>)
            return this.Equals((Optional<T>)obj);
        else
            return false;
    }
    public bool Equals(Optional<T> other)
    {
        if (HasValue && other.HasValue)
            return object.Equals(value, other.value);
        else
            return HasValue == other.HasValue;
    }
}

Note that you won't be able to emulate certain behaviors of Nullable<T>, such as the ability to box a nullable value with no value to null, rather than a boxed nullable, as it has special compiler support for that (and a some other) behavior.

Solution 2 - C#

In my opinion, any Option implementation which exposes HasValue property is the defeat of the entire idea. The point of optional objects is that you can make unconditional calls to their contents without testing whether the content is there.

If you have to test whether the optional object contains a value, then you have done nothing new compared to common null tests.

Here is the article in which I am explaining optional objects in full detail: Custom Implementation of the Option/Maybe Type in C#

And here is the GitHub repository with code and examples: https://github.com/zoran-horvat/option

If you're reluctant to use a heavyweight Option solution, then you can easily build a lightweight one. You can make your own Option<T> type which implements IEnumerable<T> interface, so that you can leverage LINQ extension methods to turn calls optional. Here is the simplest possible implementation:

public class Option<T> : IEnumerable<T>
{
    private readonly T[] data;

    private Option(T[] data)
    {
        this.data = data;
    }

    public static Option<T> Create(T value)
    {
        return new Option<T>(new T[] { value });
    }

    public static Option<T> CreateEmpty()
    {
        return new Option<T>(new T[0]);
    }

    public IEnumerator<T> GetEnumerator()
    {
        return ((IEnumerable<T>)this.data).GetEnumerator();
    }

    System.Collections.IEnumerator
        System.Collections.IEnumerable.GetEnumerator()
    {
        return this.data.GetEnumerator();
    }
}

Using this Option<T> type is done via LINQ:

Option<Car> optional = Option<Car>.Create(myCar);
string color = optional
  .Select(car => car.Color.Name)
  .DefaultIfEmpty("<no car>")
  .Single();  // you can call First(), too

You can find more about optional objects in these articles:

And you may refer to my video courses for more details on how to simplify control flow using Option type and other means: Making Your C# Code More Functional and Tactical Design Patterns in .NET: Control Flow

The first video course (Making Your C# Code More Functional) brings detailed introduction to railway-oriented programming, including the Either and Option types and how they can be used to manage optional objects and handle exceptional cases and errors.

Solution 3 - C#

There is better implementation of option type in C#. You can find this implemenation in Tactical design patterns in .NET by Zoran Horvat at pluralsight.com. It includes an explanation why and how to use it. The basic idea is to implement option class as implementation of IEnumerable<> interface.

public class Option<T> : IEnumerable<T>
{
    private readonly T[] data;

    private Option(T[] data)
    {
        this.data = data;
    }
    
    public static Option<T> Create(T element)
    {
        return new Option<T>(new[] { element });
    }

    public static Option<T> CreateEmpty()
    {
        return new Option<T>(new T[0]);
    }

    public IEnumerator<T> GetEnumerator()
    {
        return ((IEnumerable<T>) this.data).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

Solution 4 - C#

There's nothing built-in, but you can define your own. Note that an Option<T> implementation doesn't make sense without defining the map/bind operators.

public struct Option<T>
{
	private bool hasValue;
	private T value;

	public Option(T value)
	{
		if (value == null) throw new ArgumentNullException("value");
		this.hasValue = true;
		this.value = value;
	}

	public Option<TOut> Select<TOut>(Func<T, TOut> selector)
	{
		return this.hasValue ? new Option<TOut>(selector(this.value)) : new Option<TOut>();
	}

	public Option<TOut> SelectMany<TOut>(Func<T, Option<TOut>> bind)
	{
		return this.hasValue ? bind(this.value) : new Option<TOut>();
	}

	public bool HasValue
	{
		get { return this.hasValue; }
	}

	public T GetOr(T @default)
	{
		return this.hasValue ? this.value : @default;
	}
}

Solution 5 - C#

In the project "C# functional language extensions" https://github.com/louthy/language-ext exists the Option object of F# among others functional patters

Solution 6 - C#

Instead of writing your own class, you could use Microsoft.FSharp.Core.FSharpOption<T> from the FSharpCore.dll assembly. Unfortunately, the F# types are a bit clumsy when used in C#.

//Create
var none = FSharpOption<string>.None;
var some1 = FSharpOption<string>.Some("some1");
var some2 = new FSharpOption<string>("some2");

//Does it have value?
var isNone1 = FSharpOption<string>.get_IsNone(none);
var isNone2 = OptionModule.IsNone(none);
var isNone3 = FSharpOption<string>.GetTag(none) == FSharpOption<string>.Tags.None;

var isSome1 = FSharpOption<string>.get_IsSome(some1);
var isSome2 = OptionModule.IsSome(some1);
var isSome3 = FSharpOption<string>.GetTag(some2) == FSharpOption<string>.Tags.Some;

//Access value
var value1 = some1.Value; //NullReferenceException when None
var value2 = OptionModule.GetValue(some1); //ArgumentException when None

Solution 7 - C#

Perhaps this is closer to the F# Option type

public struct Option<T>
{
    private T value;
    private readonly bool hasValue;

    public bool IsSome => hasValue;

    public bool IsNone => !hasValue;

    public T Value
    {
        get
        {
            if (!hasValue) throw new NullReferenceException();
            return value;
        }
    }

    public static Option<T> None => new Option<T>();

    public static Option<T> Some(T value) => new Option<T>(value);

    private Option(T value)
    {
        this.value = value;
        hasValue = true;
    }

    public TResult Match<TResult>(Func<T, TResult> someFunc, Func<TResult> noneFunc) =>
        hasValue ? someFunc(value) : noneFunc();

    public override bool Equals(object obj)
    {
        if (obj is Option<T>)
        {
            var opt = (Option<T>)obj;
            return hasValue ? opt.IsSome && opt.Value.Equals(value) : opt.IsNone;
        }
        return false;
    }

    public override int GetHashCode() =>
        hasValue ? value.GetHashCode() : 0;
}

Solution 8 - C#

I decided to implement some kind of Optional<> Java class prototype some time ago using one of the last C# version.

Here it is:

public sealed class Optional<T>
{
    private static readonly Optional<T> EMPTY = new Optional<T>();
    private readonly T value;

    private Optional() => value = default;
    private Optional(T arg) => value = arg.RequireNonNull("Value should be presented");

    public static Optional<T> Empty() => EMPTY;
    public static Optional<T> Of(T arg) => new Optional<T>(arg);
	public static Optional<T> OfNullable(T arg) => arg != null ? Of(arg) : Empty();
	public static Optional<T> OfNullable(Func<T> outputArg) => outputArg != null ? Of(outputArg()) : Empty();

	public bool HasValue => value != null;

    public void ForValuePresented(Action<T> action) => action.RequireNonNull()(value);

    public IOption<T> Where(Predicate<T> predicate) => HasValue 
        ? predicate.RequireNonNull()(value) ? this : Empty() : this;

    public IOption<TOut> Select<TOut>(Func<T, TOut> select) => HasValue 
        ? Optional<TOut>.OfNullable(select.RequireNonNull()(value)) 
        : Optional<TOut>.Empty();

    public IOption<IOption<TOut>> SelectMany<TOut>(Func<T, IOption<TOut>> select) => HasValue 
		? Optional<IOption<TOut>>.OfNullable(select.RequireNonNull()(value)) 
		: Optional<IOption<TOut>>.Empty();

    public T Get() => value;
    public T GetCustomized(Func<T, T> getCustomized) => getCustomized.RequireNonNull()(value);
    public U GetCustomized<U>(Func<T, U> getCustomized) => getCustomized.RequireNonNull()(value);

    public T OrElse(T other) => HasValue ? value : other;
    public T OrElseGet(Func<T> getOther) => HasValue ? value : getOther();
    public T OrElseThrow<E>(Func<E> exceptionSupplier) where E : Exception => HasValue ? value : throw exceptionSupplier();

    public static explicit operator T(Optional<T> optional) => OfNullable((T) optional).Get();
    public static implicit operator Optional<T>(T optional) => OfNullable(optional);

    public override bool Equals(object obj)
    {
        if (obj is Optional<T>) return true;
        if (!(obj is Optional<T>)) return false;
        return Equals(value, (obj as Optional<T>).value);
    }

    public override int GetHashCode() => base.GetHashCode();
    public override string ToString() => HasValue ? $"Optional has <{value}>" : $"Optional has no any value: <{value}>";
}

Solution 9 - C#

If you don't like baking your own solutions, I would use Language Ext. It is available on nuget. I have recently started using this library, and the safety from null references is amazing! I am not a expert with this library, but it can do what you are asking for, and much more.

Here is a taste of what can be done:

using System;
using LanguageExt;
using static LanguageExt.Prelude;

public class Demo
{
    public static Option<int> ToEvenOrNone(int i) =>
        i % 2 == 0
            ? i.Apply(Optional)
            : None;

    public static void PrintToDebug(Option<int> value) => 
        value
            .Some(Console.WriteLine)
            .None(() => Console.WriteLine("Value is not Even!"));

    public static void Test()
    {
        for (int i = 0; i < 10; i++)
        {
            PrintToDebug(ToEvenOrNone(i));
        }
    }
}

Here is the output:

0
Value is not Even!
2
Value is not Even!
4
Value is not Even!
6
Value is not Even!
8
Value is not Even!

Solution 10 - C#

> Is there a Nullable/Optional class in C#, that forces us to test if > object exists before extracting and using it?

Nullables were created so that primitive types could be null. Their default value didn't have to be an actual value (Like int, without nullables it's default is 0, so is that a 0 means something 0 or a not set to anything 0?)

No there is nothing that you can do to force a programmer to check if an object is null. That's good though. Doing so would create an immense amount of overhead. If this was a language feature, how often would you force check? Would you require it when the variable is first assigned? What if the variable points to another object later? Would you force it to check before every method and property, and if it fails would you throw an exception? You get that now with a null reference exception. You would get very little benefit in forcing someone to do this beyond what you already have.

Solution 11 - C#

Learned a lot from Zoran Horvat's answer. Here is my code. optional can has a real value or an empty. On the consuming side, same code handle them all.

void Main()
{
	var myCar = new Car{ Color =  Color.Black, Make="Toyota"};
	
	Option<Car> optional = Option<Car>.Create(myCar);

    // optional is an Empty 50% of the time.
	if(new Random().NextDouble() > 0.5)
		optional = Option<Car>.CreateEmpty();
         	


	string color = optional
	.Select(car => car.Color.Name)
	.DefaultIfEmpty("<no car>")
	.Single();
	Console.Write(color);
}

class Car {
	public Color Color { get; set; }
	public string Make { get; set;}
}

public class Option<T> : IEnumerable<T>
{
	private readonly T[] data;

	private Option(T[] data)
	{
		this.data = data;
	}

	public static Option<T> Create(T value)
	{
		return new Option<T>(new T[] { value });
	}

	public static Option<T> CreateEmpty()
	{
		return new Option<T>(new T[0]);
	}

	public IEnumerator<T> GetEnumerator()
	{
		return ((IEnumerable<T>)this.data).GetEnumerator();
	}

	System.Collections.IEnumerator
		System.Collections.IEnumerable.GetEnumerator()
	{
		return this.data.GetEnumerator();
	}
}

Solution 12 - C#

https://github.com/mcintyre321/OneOf

I thought this oneOf class had a good re-creation of option type. It even includes a .switch/.match with pattern matching, and most importantly it works at runtime which is what you expect out of an Option pattern.

Solution 13 - C#

Use T? nullable reference instead of Option<T>

Since C#8 you should deprecate custom Option<T>-implementations. The null dilemma is now completely resolved.

T? is a complete substitution for Option<T>

C# has the following features for handling null:

  1. Null coalescing operator
  2. Null conditional operator
  3. Non nullable & nullable reference types (since C#8)
  4. Configurable compile errors/warnings

Keep in mind that

Option<Car> optional = Option<Car>.Create(myCar);
string color = optional
  .Select(car => car.Color.Name)
  .DefaultIfEmpty("<no car>")
  .Single();  // you can call First(), too

is the same as

string color = myCar?.Color.Name ?? "<no car>";

and additionally the string color is also a reference that can't be null.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHikariView Question on Stackoverflow
Solution 1 - C#ServyView Answer on Stackoverflow
Solution 2 - C#Zoran HorvatView Answer on Stackoverflow
Solution 3 - C#Lukáš KmochView Answer on Stackoverflow
Solution 4 - C#LeeView Answer on Stackoverflow
Solution 5 - C#aloonView Answer on Stackoverflow
Solution 6 - C#tearvisusView Answer on Stackoverflow
Solution 7 - C#gileCADView Answer on Stackoverflow
Solution 8 - C#E. AnagnostopoulosView Answer on Stackoverflow
Solution 9 - C#WrmcodeblocksView Answer on Stackoverflow
Solution 10 - C#kemiller2002View Answer on Stackoverflow
Solution 11 - C#Rm558View Answer on Stackoverflow
Solution 12 - C#user549442View Answer on Stackoverflow
Solution 13 - C#Felix KeilView Answer on Stackoverflow