Futurum.Core 1.0.15

There is a newer version of this package available.
See the version list below for details.
dotnet add package Futurum.Core --version 1.0.15                
NuGet\Install-Package Futurum.Core -Version 1.0.15                
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="Futurum.Core" Version="1.0.15" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Futurum.Core --version 1.0.15                
#r "nuget: Futurum.Core, 1.0.15"                
#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.
// Install Futurum.Core as a Cake Addin
#addin nuget:?package=Futurum.Core&version=1.0.15

// Install Futurum.Core as a Cake Tool
#tool nuget:?package=Futurum.Core&version=1.0.15                

Futurum.Core

license CI Coverage Status NuGet version

A dotnet library providing Option and Result data types, based on the concepts behind 'Railway Oriented Programming'

  • Result data type encapsulating computational result that represents the result that is either a success or a failure
  • Option data type that represents a value that is either present or not present
  • Based on the concepts behind Railway Oriented Programming
  • Extension methods that allows interacting with and going into and out of the Result and Option data types
  • Tested solution > 99% test coverage
  • Fluent discoverable and commented API

Full Documentation

Result

The Result data type is a type that represents the result of a computation that can either be a success or a failure. It is a type that is either a Success or a Failure.

It is a struct, preventing you from returning null instead.

This come in two forms:

  • without a payload - Result
  • with a payload - Result<T>

Any method that can fail should return a Result or Result<T>.

There are extension methods that allow you to easily convert dotnet or third-party dotnet libraries to return Result.

Note: There are async version of all the extension methods.

ResultError

Failures are represented as by the IResultError interface. These represent the context of the error.

This interface has two implementations:

  • IResultErrorNonComposite
  • IResultErrorComposite
IResultErrorNonComposite

This is the base interface for all IResultError implementations that are not composite, i.e. have no children.

IResultErrorComposite

This is the base interface for all IResultError implementations that are composite, i.e. have children.

What ResultError's come built-in

There are a number of built-in IResultError implementations.

You are free to create your own, by implementing either the IResultErrorNonComposite or IResultErrorComposite interfaces.

ResultErrorMessage

Represents a string error message, without any other context.

ResultErrorException

Represents a exception error.

ResultErrorEmpty

Represents an empty error message, this is mainly used internally in the library.

ResultErrorComposite

This is a special IResultError, it allows you to have a tree structure of IResultError's.

What to do with them

There are four supported ways to get the data from an IResultError:

  • GetErrorString
  • GetErrorStringSafe
  • GetErrorStructure
  • GetErrorStructureSafe
GetErrorString

This gets a string representing the error(s). Different implementation of IResultError deal with this differently.

ResultErrorComposite will call GetErrorString on all of their children, separating them with the specified separator.

GetErrorStringSafe

This gets a string representing the error(s). Different implementation of IResultError deal with this differently.

ResultErrorComposite will call GetErrorStringSafe on all of their children, separating them with the specified separator.

Note: The error message will be safe to return to the client, that is, it will not contain any sensitive information e.g. StackTrace.

GetErrorStructure

This gets a tree structure representing the error(s). This tree structure is serializable to Json.

ResultErrorComposite will call GetErrorStructure on all of their children, and add them as children to the ResultErrorComposite.

GetErrorStructureSafe

This gets a tree structure representing the error(s). This tree structure is serializable to Json.

ResultErrorComposite will call GetErrorStructureSafe on all of their children, and add them as children to the ResultErrorComposite.

Note: The error message will be safe to return to the client, that is, it will not contain any sensitive information e.g. StackTrace.

Extension Methods

There are extension methods that allow you to easily convert dotnet or third-party dotnet libraries to return Result.

Note: There are async version of all the extension methods.

Combine

Allows you to combine multiple Result's into one, if they have the same payload types.

If there is no payload on the Results passed in:
  • If all of the Results passed are success, then return a Result success
  • If any of the Results passed are failed, then return a Result failure with a ResultError of all of the failure ResultError's
If there are payloads on the Results passed in and they are all the same type:
  • If all of the Results passed are success, then return a Result success with an IEnumerable of all the Result payloads
  • If any of the Results passed are failed, then return a Result failure with a ResultError of all of the failure ResultError's
If there are IEnumerable payloads on the Results passed in and they are all the same type:
  • If all of the Results passed are success, then return a Result success with an IEnumerable of all the Result payloads concatenated together
  • If any of the Results passed are failed, then return a Result failure with a ResultError of all of the failure ResultError's
CombineAll

Allows you to combine Result's that have different payload types.

You additionally pass in a selector func.

Compensate

Allows you to provide a compensating action (that also returns a Result), if the Result is:

  • a failure
CompensateWhen

Allows you to provide a compensating action (that also returns a Result), if the Result is:

  • a failure of a specific type
  • matches a predicate optional
CompensateWhenAny

Allows you to provide a compensating action (that also returns a Result), if the Result is:

  • a failure of a specific type
  • matches a predicate optional

Note: this will flatten a ResultErrorComposite.

Do - Perform side-effect only on success

Executes a side-effect if the Result is success.

DoWhenFailure - Perform side-effect only on failure

Executes a side-effect if the Result is failure.

DoSwitch - Perform side-effect

Allows you to perform a side-effect on an Result<T>.

You have to say what to do when the value is success and failure.

EnhanceWithError

Allows you to provide additional context to a failure.

Note: This will create a ResultErrorComposite, with the parent IResultError being the error passed in and the existing IResultError its children.

Factory
Result.Ok and Result.Ok<T>
  • Creates a success Result
  • Creates a success Result<T> with the payload provided
Result.Fail
  • Creates a failure Result with the error provided
  • Creates a failure Result<T> with the error provided
ToResultOk - Result → Result<T>

Creates a success Result<T> with the payload provided

FlatMap
Map - Result<T> → Result<TR>

Transforms an Result<T> to an Result<TR>.

The transformation will only occur if there is the Result is success.

It is assumed that the transformation func that you pass in cannot fail, i.e. throw an exception. If it can throw an exception, use Then, returning a Result<TR> from the transformation func.

MapSwitch

Transforms an Result<T> to a Result<TR>

Switch

Allows you to transform an Result<T> to a TR.

You have to say what to return when the value is success and failure.

Then - Result<T> → Result<TR>

Allows you to bind two Result or Result<T> methods together.

ThenSwitch

Transforms an Result<T> to a Result<TR>

Allows you to specify a predicate to change the way the Result is transformed.

ThenTry

Allows you to execute a func wrapping it in a try / catch

  • If an exception is thrown, it will return a Result.Fail
  • If no exception is thrown it will return a Result.Ok

The result of this is then passed to the then func

Note: This can be a good way to integrate third-party libraries.

Note: This is really Result.Try and Result.Then combined.

ToNonGeneric - Result<T> → Result

Discards the payload.

Try

Will run the func wrapping it in a try / catch.

  • If an exception is thrown, it will return a Result.Fail
  • If no exception is thrown it will return a Result.Ok

This can be a good way to integrate third-party libraries.

Unwrap - Result<T> → T or Exception

Comes out of the Result monad.

  • If the Result is Ok, then return the value if there is one
  • If the Result is Fail, then throw an exception, passing through the ResultError data
Enumerable
Choose

Return only those elements of a sequence of Result<T> that are success.

If none of the elements in the sequence are success, then a Result<T> failure is returned.

Filter

Filters an IEnumerable>Result<T>> based on a predicate

FlatMapAs

Transforms an Result<IEnumerable>T>> to a IEnumerable>Result<T>>

MapAs

Transforms an Result<IEnumerable>T>> to a Result<IEnumerable>TR>>

Pick

Return the first element of a sequence of Result<T> that are success.

If none of the elements in the sequence match are success, then a Result<T> failure is returned.

PickFailureOrSuccess

Return the first element of a sequence of Result that are failure.

If none of the elements in the sequence match are failure, then a Result failure is returned.

ThenAs

Transforms an Result<IEnumerable>T>> to a Result<IEnumerable>TR>>

TryFirst

Sequentially runs through a sequence of elements applying a function that returns a Result<TR>. The first one that is success is returned.

TryToDictionary

Try to create a Dictionary<TKey, TElement;> from an IEnumerable>T> according to specified key selector and element selector functions.

Note: This will explicitly checks for duplicate keys and return a Result<Dictionary<TKey, TElement>> failure if there are any.

AsyncEnumerable
Choose

Return only those elements of a sequence of Result<T> that are success.

If none of the elements in the sequence are success, then a Result<T> failure is returned.

Filter

Filters an IEnumerable>Result<T>> based on a predicate

MapAs

Transforms an Result<IEnumerable>T>> to a Result<IEnumerable>TR>>

Interop with Option
Option → Result

You can move between an Option and a Result using the 'ToResult' extension method. You just need to provide the error if the Option is not present.

Result → Option

This is not supported as it would result in the loss of the error context.

Option

The Option data type is a type that represents a value that is either present or not present. It is a type that is either HasValue or HasNoValue.

It is a struct, preventing you from returning null instead.

It can be used for value and reference types.

Extension Methods

Map - Option<T> → Option<TR>

Allows you to transform an Option<T> to an Option<TR>.

The transformation will only occur if there is a value present.

Switch - Option<T> → TR

Allows you to transform an Option<T> to a TR.

You have to say what to return when the value is present and not present.

DoSwitch - Perform side-effect

Allows you to perform a side-effect on an Option<T>.

You have to say what to do when the value is present and not present.

TryGetValue - Get a value from a Dictionary

The TryGetValue extension methods work with dictionary.

They get the value from a dictionary as an Option<T>.

Factory - T → Option<T>

There are a number of factory extension methods.

From

Converts a T to an Option<T>

If the value is not null, then it will be a Option<T> with the value on it.

If the value is null, then it will be a Option<T> with the value not set.

None

Returns a Option<T> with the value not set.

ToOption

Converts a T to an Option<T>

If the value is not null, then it will be a Option<T> with the value on it.

If the value is null, then it will be a Option<T> with the value not set.

Implicit conversion

There is an implicit conversion in place. So if your method returns an T, then it will be automatically converted to an Option<T>.

OrElse and GetValueOrDefault

The OrElse extension methods are good when you have a precedence order.

The GetValueOrDefault extension methods are used to as a terminating method and will take you out if an Option, returning the default value provided if the Option has no value.

TryParse

There are a lot of TryParse extension methods provided, for a lot of the built-in framework types:

  • Bool
  • Int
  • Long
  • Decimal
  • Double
  • Float
  • Guid
  • DateTime
  • DateOnly
  • TimeOnly
  • Enum
LINQ
TryElementAt

Returns the element at a specified index in a sequence.

  • If the index is out of range, then an Option<T>.None is returned.
  • If the index is in range, the element at the specified position in the source sequence is returned as a Option<T>.
TryFirst

Returns the first element of a sequence.

  • If the sequence is empty, then an Option<T>.None is returned.
  • If the sequence is not empty, the first element is returned as a Option<T>.
TryLast

Returns the last element of a sequence.

  • If the sequence is empty, then an Option<T>.None is returned.
  • If the sequence is not empty, the last element is returned as a Option<T>.
TrySingle

Returns the only element of a sequence.

  • If the sequence is empty, then an Option<T>.None is returned, wrapped in a Result<T>.IsSuccess.
  • If the sequence has 1 value, then the value is returned as a Option<T>, wrapped in a Result<T>.IsSuccess.
Enumerable<Option<T>>
Choose

Return only those elements of a sequence of Option<T> that have a value.

Map

Transforms each element of a sequence into a new form.

MapSwitch

Transforms each element of a sequence based, allows you to pass in seperate transformations for if the value is there or not.

Pick

Return the first element of a sequence based on if the value is there.

If none of the elements in the sequence match the predicate, then Option<T>.None is returned.

Interop with Nullable

For structs there is interop with Nullable

Nullable → Option

Use the ToOption extension method.

Option → Nullable

Use the ToNullable extension method.

Interop with Result
Option → Result

You can move between an Option and a Result using the 'ToResult' extension method. You just need to provide the error if the Option is not present.

Result → Option

This is not supported as it would result in the loss of the error context.

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

NuGet packages (7)

Showing the top 5 NuGet packages that depend on Futurum.Core:

Package Downloads
Futurum.WebApiEndpoint

A dotnet library that allows you to build WebApiEndpoints using a vertical slice architecture approach. Provides a structured way to create REST apis in dotnet without controllers.

Futurum.Test

Small dotnet testing library, allowing you to test code that uses Futurum.Core

Futurum.FluentValidation

A dotnet library, that allows FluentValidation to work with Futurum.Core.

Futurum.ApiEndpoint

A dotnet library, that is the base for ApiEndpoints in Futurum.

Futurum.Core.Polly

Small dotnet library, allowing you to use [Polly](https://github.com/App-vNext/Polly) with Futurum.Core, based on the concepts behind 'Railway Oriented Programming'.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.16 526 4/10/2023
1.0.15 392 4/7/2023
1.0.14 354 3/26/2023
1.0.13 809 11/18/2022
1.0.12 431 11/3/2022
1.0.11 1,279 6/3/2022
1.0.10 566 4/4/2022
1.0.9 421 4/3/2022
1.0.8 577 3/21/2022
1.0.7 401 3/19/2022
1.0.6 1,701 2/24/2022
1.0.5 545 2/23/2022
1.0.4 421 2/20/2022
1.0.3 1,106 2/2/2022
1.0.2 428 1/28/2022
1.0.1 2,128 1/28/2022