SoftwareMadeSimple.SimpleResults 1.0.1

dotnet add package SoftwareMadeSimple.SimpleResults --version 1.0.1
                    
NuGet\Install-Package SoftwareMadeSimple.SimpleResults -Version 1.0.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="SoftwareMadeSimple.SimpleResults" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SoftwareMadeSimple.SimpleResults" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="SoftwareMadeSimple.SimpleResults" />
                    
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 SoftwareMadeSimple.SimpleResults --version 1.0.1
                    
#r "nuget: SoftwareMadeSimple.SimpleResults, 1.0.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.
#:package SoftwareMadeSimple.SimpleResults@1.0.1
                    
#: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=SoftwareMadeSimple.SimpleResults&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=SoftwareMadeSimple.SimpleResults&version=1.0.1
                    
Install as a Cake Tool

SoftwareMadeSimple.SimpleResults.Result<T, E>

A simple, immutable result type for representing success or failure in C# (.NET 8, C# 12).

Features

  • Encapsulates either a success value (T) or an error (E).
  • Provides static factory methods for success and failure.
  • Implicit conversion from value or error.
  • Nullable properties for value and error.
  • IsSuccess and IsFailure properties for easy result checking.
  • Uses [MemberNotNullWhen] attributes for improved nullability analysis.

Usage

The SimpleResults library uses implicit conversion to allow you to easily create results from values or errors.

private static SimpleResults.Result<int, string> NotZero(int input)
{
    if (input == 0)
        return "Input may not be zero";

    return input;
}

Use the Value property when the result IsSuccess to check the result:

var input = 1;

var result = NotZero(input);

Assert.That(result.IsSuccess, Is.True);
Assert.That(result.Value, Is.EqualTo(input));

Use the Error property when the result IsFailure to check the error:

var input = 0;

var result = NotZero(input);

Assert.That(result.IsFailure, Is.True);
Assert.That(result.Error, Is.EqualTo("Input may not be zero"));

Accessing the Value when the result is a failure will throw an InvalidOperationException.


var input = 0;

var result = NotZero(input);

Assert.That(result.IsFailure, Is.True);
Assert.That(() => result.Value, Throws.InvalidOperationException);

Accessing the Error when the result is a success will throw an InvalidOperationException.

var input = 1;

var result = NotZero(input);
            
Assert.That(result.IsSuccess, Is.True);
Assert.That(() => result.Error, Throws.InvalidOperationException);

When the value type and error type are the same, implicit conversion doesn't work. Use the static Success and Failure methods to create the result:

private static SimpleResults.Result<string, string> Validated(string? input)
{
    if (string.IsNullOrWhiteSpace(input))
        return SimpleResults.Result<string, string>.Failure("Input may not be null or whitespace");

    return SimpleResults.Result<string, string>.Success(input);
}

In practice, having the same type for both value and error should be rare, but this pattern allows you to handle such cases cleanly.

In my experience, having a dedicated error type is often more beneficial, as it allows for richer error handling and avoids confusion with the value type. For example:

private static SimpleResults.Result<int, NotZeroError> NotZero(int input)
{
    if (input == 0)
        return NotZeroError.InputMayNotBeZero;

    return input;
}

private enum NotZeroError
{
    InputMayNotBeZero
}

Philosophy

Many methods don't have a single return value, but rather a success or failure value. Using exceptions for control flow is both expensive and confusing, so many developers resort to using a Result object of some kind.

The SimpleResults library is designed to provide a straightforward and efficient way to handle success and failure in C# applications. It aims to reduce boilerplate code while maintaining clarity and type safety. The use of implicit conversions simplifies the creation of results, making it easy to work with both success values and errors without excessive verbosity.

For this library, I decided not to use a Match function to access the values, as is common in a functional programming style. This is a conscious design choice. In my experience, using Match is confusing for many developers who aren't familiar with a functional style of programming. Once you go the functional route, it often affects the rest of your codebase, which is not always desirable. Instead, I opted for a more traditional approach that leverages properties like Value and Error, making it easier for developers to understand and use without needing to learn new patterns.

I've added [MemberNotNullWhen] attributes to the properties to improve nullability analysis, ensuring that the compiler can better understand when these properties are guaranteed to be non-null.

License

MIT

Product Compatible and additional computed target framework versions.
.NET 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 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  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.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 59 8/22/2025
1.0.0 109 8/19/2025

Initial version