Reditus 2.1.1

dotnet add package Reditus --version 2.1.1                
NuGet\Install-Package Reditus -Version 2.1.1                
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="Reditus" Version="2.1.1" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Reditus --version 2.1.1                
#r "nuget: Reditus, 2.1.1"                
#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 Reditus as a Cake Addin
#addin nuget:?package=Reditus&version=2.1.1

// Install Reditus as a Cake Tool
#tool nuget:?package=Reditus&version=2.1.1                

Reditus

NuGet Version NuGet Downloads

Reditus, is a Result pattern library for every .NET application.

Getting Started

You can install Reditus with NuGet:

 Install-Package Reditus

Features

  • Versatile — Can be used in any .NET project.
  • Immutable — Once a Result is created, it cannot be changed.
  • Detailed on Failure — A Result, when failed, contains a specific Error class.
  • With focus on DX — Supports the implicit operator so it does not clutter your code.
  • Thread safe — Results are immutable and by nature, safe to work with in multithreaded scenarios.
  • Extensible — Extend the Result class or the Error class by introducing your very own classes.
  • Fully tested — The code has full coverage.

Usage

The Result object can be used as flow state control.

The Result<T> object can hold any value. A class, a value-type, a struct, anything.

Creating a Result

Typically, the Result class is being used by methods that don't return a value.

var result = Result.CreateSuccess(); // creates a result in success state

var result = Result.CreatFail(); // creates a result in fail state

var error = new Error("An error occured."); // the error can also hold a message
var result = Result.CreatFail(error);

// the error can also hold an exception
var error = new Error("An error occured.", new Exception());
var result = Result.CreatFail(error);

An example usage of the Result class.

public async Task<Result> ExecuteJob()
{
    try
    {
        var jobId = ExecuteJob();

        if (jobId == 0)
        {
            // create an Error indicating the reason of failure
            var error = new Error("Cleanup job was not executed.");

            return Result.CreateFail(error);
        }

        return Result.CreateSuccess();
    }
    catch (Exception ex)
    {
        // create an Error and attach the exception
        var error = new Error("An unexpected error occured while trying execute Cleanup job.", ex);

        return Result.CreateFail(error);
    }
}

The Result class also supports the implicit operator.

public async Task<Result> ExecuteJob()
{
    try
    {
        var jobId = ExecuteJob();

        if (jobId == 0)
        {
            // create an Error indicating the reason of failure
            var error = new Error("Cleanup job was not executed.");

            return error; // this implicitly is being converted into Result.CreateFail(error);
        }

        return Result.CreateSuccess(); // no implicit operator can be used since there is not value
    }
    catch (Exception ex)
    {
        // create an Error and attach the exception
        var error = new Error("An unexpected error occured while trying execute Cleanup job.", ex);

        return error;
    }
}

The Result<T> class is being used by methods that return a value.

var result = Result<int>.CreateSuccess(1); // creates a result in success state

var result = Result<int>.CreateFail(); // creates a result in fail state

// the error can also hold a message
var error = new Error("An error occured.");
var result = Result.CreateFail(error);

// the error can also hold an exception
var error = new Error("An error occured.", new Exception());
var result = Result<int>.CreateFail(error);

An example usage of the Result<T> class.

public async Task<Result<int>> ExecuteJob()
{
    try
    {
        var jobId = ExecuteCleanupJob();

        if (jobId == 0)
        {
            // create an Error indicating the reason of failure
            var error = new Error("Cleanup job was not executed.");

            return Result<int>.CreateFail(error);
        }

        return Result<int>.CreateSuccess(jobId);
    }
    catch (Exception ex)
    {
        // create an Error and attach the exception
        var error = new Error("An unexpected error occured while trying execute Cleanup job.", ex);

        return Result<int>.CreateFail(error);
    }
}

The Result<T> class also supports the implicit operator.

public async Task<Result<int>> ExecuteJob()
{
    try
    {
        var jobId = ExecuteCleanupJob();

        if (jobId == 0)
        {
            // create an Error indicating the reason of failure
            var error = new Error("Cleanup job was not executed.");

            return error; // this implicitly is being converted into Result<int>.CreateFail(error);
        }

        return jobId; // this implicitly is being converted into Result<int>.CreateSuccess(error);
    }
    catch (Exception ex)
    {
        // create an Error and attach the exception
        var error = new Error("An unexpected error occured while trying execute Cleanup job.", ex);

        return error;
    }
}

The anatomy of a Result

A Result holds certain information about itself.

var result = Result.CreateSuccess();

result.IsSuccessful // true
result.IsFailed // false
result.Error // throws InvalidOperationException as the result is not in a failed state


var result = Result.CreateFail();

result.IsSuccessful // false
result.IsFailed // true
result.Error // Error instance

When the Result<T> holds a return value.

var result = Result<int>.CreateSuccess(1);

result.IsSuccessful // true
result.IsFailed // false
result.Value // 1
result.Error // throws InvalidOperationException as the result is not in a fail state


var result = Result<int>.CreateFail();

result.IsSuccessful // false
result.IsFailed // true
result.Value // throws InvalidOperationException as the result is not in a success state
result.Error // IError instance

Extending

You can introduce your very own Error classes by extending the existing one.

The below custom NotFoundError class is being used when an application might need to return a NotFound 404 response.

public interface ICustomError : IError
{
    public HttpStatusCode HttpStatusCode { get; }
}

public sealed class NotFoundError : Error, ICustomError
{
    public HttpStatusCode HttpStatusCode => HttpStatusCode.NotFound;

    public NotFoundError(string message)
        : base(message)
    {
    }
}

An example of the above custom Error class.

public async Task<Result<IEnumerable<Project>>> GetProjects()
{
    try
    {
        var projects = await GetProjects();

        if (!projects.Any())
        {
            var error = new NotFoundError("The request resource was not found."); // <-- the new NotFoundError Error class

            return error;
        }

        return jobId;
    }
    catch (Exception ex)
    {
        // create an Error and attach the exception
        var error = new Error("An unexpected error occured while trying execute Cleanup job.", ex);

        return error;
    }
}

The Error class provides many constructors, so you are free to use whichever suits your needs best. See definition

Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  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 is compatible.  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 is compatible.  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.  net9.0 is compatible. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 is compatible. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.
  • .NETStandard 2.1

    • No dependencies.
  • net5.0

    • No dependencies.
  • net6.0

    • No dependencies.
  • net7.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Reditus:

Package Downloads
Reditus.Benchmarks

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
2.1.1 74 11/16/2024
2.1.0 105 10/6/2024
2.0.4 95 10/5/2024
2.0.3 93 10/5/2024
2.0.2 95 10/5/2024
2.0.0 113 5/6/2024
1.0.0 89 5/3/2024