Toarnbeike.Optional 1.1.0

dotnet add package Toarnbeike.Optional --version 1.1.0
                    
NuGet\Install-Package Toarnbeike.Optional -Version 1.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Toarnbeike.Optional" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Toarnbeike.Optional" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Toarnbeike.Optional" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Toarnbeike.Optional --version 1.1.0
                    
#r "nuget: Toarnbeike.Optional, 1.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Toarnbeike.Optional@1.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Toarnbeike.Optional&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Toarnbeike.Optional&version=1.1.0
                    
Install as a Cake Tool

CI .NET 10 License: MIT

Toarnbeike.Optional

This package provides a **lightweight and expressive Option (Maybe) monad for C#, inspired by functional programming, while remaining idiomatic to the .NET ecosystem.

An Option<TValue> represents a value that can either be there, or be absent, without reling on nulls. It improves code clarity and safety by making the absence of a value explicit, replacing null checks and exceptions with a functional approach.

Features

  • Fluent API for working with optional values
  • Implicit conversion from values and Option.None
  • Rich functional extensions (Map, Bind, Match, Tap and others)
  • Async support for all extensions
  • Rich LINQ-style extensions for IEnumerable<Option<T>>
  • Linq integration (query syntax)
  • Test extensions for fluent assertions
  • Comprehensive XML documentation and usage examples
  • Unit tested with full code coverage

Contents

  1. Quick start
  2. Core concepts
  3. Extensions
  4. Collections
  5. Linq query syntax
  6. Try helpers
  7. Test extensions
  8. Why Options?

Quick start

This example demonstrates the most common workflow when using Options: construction, transformation and consumption.

using Toarnbeike.Optional;			
using Toarnbeike.Optional.Extensions;

Option<string> message = "Hello World!";
Option<string> missing = Option.None;

// Transform the value
var messageLength = message.Map(value => value.Length); // Option<int> with value 12
var newMissing = missing.Map(_ => "Not executed");      // Option<string>, still None.

// Console the value
Console.WriteLine($"Message had {messageLength.Reduce(0)} characters");    // Message had 12 characters
Console.WriteLine($"Missing was replaced by: {newMissing.Reduce("Hello")}; // Missing was replaced by: Hello

Key properties of working with Unions:

  • null values and nullable notition is replaced with Option.
  • Values are never consumed directly, but always using a Reduce() to provide an alternative for a missing value.
  • Mapping, binding, etc. leafs the value in an Option state, and missing values are still Option.None.

Core Concepts

An option can represent either a value (Some) or no value (None):

var option1 = Option<int>.Some(1);
var option2 = Option.Some(1);        // Type inferred
var option3 = Option<int>.None();

Option<int> option4 = 1;             // Implicit conversion
Option<int> option5 = Option.None;

Extracting the value:

if (option1.TryGetValue(out var value))
{
    Console.WriteLine(value); // Outputs: 1
}

Extension Methods

The Toarnbeike.Optional.Extensions namespace includes rich extensions for Option<T>:

Available Extensions

Method Returns Description
AsNullable() T? Convert to nullable
AsOption() Option<T> Convert from nullable
Map(...) Option<U> Transforms the inner value
Bind(...) Option<U> Chain operations returning Option<T>
Check(...) Option<T> Filter by predicate
IsSomeAnd(...) bool Check if value matches value or predicate
Match(...) U Pattern match: Some/ None
Reduce(...) T Fallback to a value if empty
OrElse(...) Option<T> Return current option or fallback if None
Tap(...) Option<T> Execute side-effect on value
TapIfNone() Option<T> Execute side-effect when empty

All extensions include async overloads and Task<Union<...>> variants.

For information per method, see the Extensions README.


Collections

The Toarnbeike.Optional.Collections namespace contains extension methods to work with IEnumerable<Option<T>>:

Method Returns Description
Values() IEnumerable<T> Get all non None values.
WhereValues(...) IEnumerable<T> Get all non None values with predicate
SelectValues(...) IEnumerable<U> Get all non None values and apply selector
CountValues() int Get count of non None values
AnyValues() bool Check if collection has any values
AllValues() bool Check if collection contains only values
FirstOrNone() Option<T> Get first non None value in collection
LastOrNone() Option<T> Get last non None value in collection

Many of these methods come with predicate overloads to add additional filters, similar to their Linq equivalence.

For information per method, see the Collections README.

Collections of T

In addition to extensions on IEnumerable<Option<T>>, the Toarnbeike.Optional.Collections namespace also contains extension methods that work on IEnumerable<T>:

Method Returns Description
FirstOrNone() Option<T> Get the first not null instance or return Option.None
LastOrNone() Option<T> Get the last not null instance or return Option.None
SingleOrNone() Option<T> Get the only instance or return Option.None

All these methods also come with predicate overloads to add additional filters. These methods are also described in more detail in the Collections README.


Linq query syntax

Toarnbeike.Optional supports optional integration with C# LINQ query syntax, making it easier to compose multiple Option<T> computations in a declarative style.

Why use LINQ Query Syntax?

While method chaining works well for most scenarios, C#`s LINQ query syntax can make some workflows more expressive and readable; especially when you want to:

  • Name intermediate options using let
  • Compose complex Option pipelines in a declarative way
  • Avoid deeply nested lambdas in Bind and Map

Example:

using Toarnbeike.Optional.Linq;

var option =
    from id in GetUserId()
    from user in GetUserById(id)
    let fullName = $"{user.FirstName} {user.LastName}"
    select new UserDto(fullName, user.Email);

When comparing that with method chaining, the LINQ query syntax can be more readable, especially for complex workflows:

var option = GetUserId()
    .Bind(GetUserById)
    .Map(user =>
    {
        var name = $"{user.FirstName} {user.LastName}";
        return new UserDto(name, user.Email);
    });

Which also works, but makes name only available inside the Map lambda.


Try Helpers

Use Option.Try(...) to wrap exception-throwing code like parsing, config loading, etc.
Returns Option.None when an exception occurs (with optional filtering and logging).

var result = Option.Try(() => int.Parse("123")); // Option.Some(123)
var fallback = Option.Try(() => int.Parse("abc")); // Option.None

// With optional filtering and logging
var parsed = Option.Try(
    () => int.Parse("abc"),
    ex => ex is FormatException,
    ex => logger.Warn(ex, "Invalid number")
);

Test extensions

The Toarnbeike.Optional.TestExtensions namespace provides simple assertion methods to improve test readability for Option<T> instances. These methods are Test Framework Agnostic, as they throw a custom AssertionFailedException. The naming is inspired by Shouldly.

The following assertions are included:

Method Description
ShouldBeSome(...) Asserts that the option is Some
ShouldBeSomeWithValue(...) Asserts Some and compares value with expected.
ShouldBeSomeThatMatches(...) Asserts Some and applies a predicate to the value.
ShouldBeSomeThatSatisfies(...) Asserts Some and applies an additional assertion.
ShouldBeNone(...) Asserts that the option is None.

Why Options?

Because nulls are dangerous and exceptions are control-flow. Using Option<T>:

  • Makes absence explicit
  • Forces handling at compile time
  • Composes beautifully in pipelines

Make illegal states unrepresentable.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Toarnbeike.Optional:

Package Downloads
Toarnbeike.Optional.TestExtensions

Fluent testing assertions for Option types

Toarnbeike.Results.Optional

Convert between Toarnbeike.Results an Toarnbeike.Optional

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.0 108 12/31/2025
1.0.1 616 7/25/2025
1.0.0 506 7/25/2025