Avig.Result 1.0.2

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

Avig.Result

Outcomes as return values instead of exceptions. No dependencies.

using Avig;

Result<User> result = await _users.Find(id);

if (result.IsFailure(out string? error, out ResultStatus status))
{
    return Result<Profile>.Failure(error, status);
}

Installation

dotnet add package Avig.Result

The package has no dependencies and targets net10.0.

Why

Throwing for an expected outcome — "not found", "wrong password", "that name is taken" — does two things at once: it cuts the call chain short, and it hides the possibility in a catch somewhere else. Result makes the outcome part of the signature instead, so the type says what can go wrong and the compiler reminds you to handle it.

Exceptions remain for what they are good at: the things nobody expected.

The Try pattern

IsSuccess and IsFailure hand out the value and the error respectively:

if (result.IsSuccess(out User? user))
{
    // user is not null here — [NotNullWhen] tells the compiler so
    Console.WriteLine(user.Name);
}

That is why the type does not offer Data as the ordinary way to reach the value. A Data property has to be nullable to work on failure, and then every call site grows a ! or a null check the compiler cannot help with. With the out form, the compiler knows the value is there in the branch where it is there.

Status

ResultStatus tells the failures apart so the caller can translate them — typically into an HTTP status — without parsing error messages as text:

Status Means
Ok succeeded
NotFound did not exist
Invalid input rejected by validation
Unauthorized not signed in
Forbidden signed in but not allowed
Conflict clashes with existing state
Unavailable a dependency did not answer
Error anything else

Every status has its own factory method: Result<T>.NotFound(), Result.Forbidden() and so on. There is also an implicit conversion from the value, so return user; is enough where the return type is Result<User>.

Building and releasing

dotnet test Avig.Result.slnx     # 12 tests
./publish.ps1                    # tests, packs, shape-checks, copies to the local feed
./release.ps1 -DryRun            # says which version a release would produce
./release.ps1 -Push              # bumps, tags and publishes to nuget.org

publish.ps1 fails if the package picks up a dependency. That is deliberate: the type sits at the bottom of every call chain in every project that uses it, so a dependency that sneaks in lands on all of them with no way to opt out.

The tag is what publishes — release.ps1 pushes vX.Y.Z, which runs .github/workflows/publish.yml. That builds the package again on a runner and pushes it to nuget.org through Trusted Publishing. No API key is stored anywhere.

License

MIT. See LICENSE.

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

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.2 109 9/22/2026

First public release. Result and Result<T> moved out of the Medusa solution into a repository and package of their own, since the type has nothing to do with Medusa. The code is unchanged; what is new is the licence, SourceLink and a symbol package.