Skip to content

Result.Net provides a result object to be used as a wrapper over operations execution results to indicate success or failure, instead of throwing exceptions or returning false without explanation.

License

Notifications You must be signed in to change notification settings

YoussefSell/Result.Net

Repository files navigation

Result.Net

Build

Modern, expressive, and safe error handling for .NET β€” ditch exception-based flows and unclear return values for a clean, composable Result type that clearly communicates intent.

🎯 Key Features

  • βœ… Clear success/failure states β€” no more silent failures or unchecked exceptions
  • 🎁 Generic payload support β€” Result<T> carries data on success
  • 🧠 Rich error info β€” include messages, error codes, and structured ResultError entries
  • πŸ”„ Exception conversion β€” use ex.ToResult() to map exceptions to Result objects
  • 🧡 Traceable failures β€” each failure auto-generates a LogTraceCode for seamless logging
  • πŸ”— Fluent API β€” chain .WithMessage(), .WithCode(), .WithErrors() easily
  • ✳️ Support for localized messages β€” use .WithLocalizedMessage() for multi-language apps
  • 🧩 Pattern matching support β€” .Match(onSuccess, onFailure) for clean outcome handling

πŸ“š Resources & Samples

πŸ“¦ Samples

Explore example usage:

  • Console app under samples/Result.Net.Samples.Console
  • AspNetCore app (with MediatR) under samples/Result.Net.Samples.AspNetCore

πŸ“– Documentation & Tutorials


βš™οΈ Quick Setup

To get started, install the package using NuGet:

Install-Package Result.Net

Then start returning Result or Result instead of throwing or returning false.

πŸ’‘ Sample Usage

// to create success result
var successResult = Result.Success();

// to create a failure result
var failedResult = Result.Failure();

To create a result wrapper for a value, you can use Result<TValue>:

// to create success results with different types of values
var successResult1 = Result.Success(30.15f);
var successResult2 = Result.Success<float>(55.5f);
var successResult3 = Result.Success(new SampleObject());
var successResult4 = Result.Success(new List<string> { "item1" });
Result<List<string>> successResult5 = new List<string> { "item1" };

// to create a failed result for a float value
var failedResult = Result.Failure<float>();

Typically you will return the Result or Result<T> from your methods:

// for methods with no return value (void)
public Result DoSomething()
{
  if (this.SomethingShouldNotBeTrue())
      return Result.Failure();

  // other logic

  return Result.Success();
}

// for methods with a return value
public Result<int> DoSomething()
{
  if (this.SomethingShouldNotBeTrue())
      return Result.Failure<int>();

  // other logic

  return 10;
}

To associate messages with the result instance for a clear idea of what happened:

// to create success result with a message
var successResult = Result.Success<float>(55.5f)
  .WithMessage("Operation Succeeded");

// to create a failed result with a message
var failedResult = Result.Failure<float>()
  .WithMessage("Operation Failed");

You can also use localized messages; more details can be found here:

// to create a failed result with a localized message
var failedResult = Result.Failure<float>()
  .WithLocalizedMessage("some_text_code");

You can utilize error codes to give a better explanation of what happens (useful for machine-to-machine communication):

// create a failed result with a message and code
var failedResult = Result.Failure()
  .WithMessage("The provided email is not valid")
  .WithCode(ResultCode.InvalidEmail);

Note: There is a list of predefined error codes that I use frequently; you can find them in ResultCode or simply use any string value.

You can also provide a ResultError to better define what happened:

var failedResult = Result.Failure()
  .WithMessage("The provided email is not valid")
  .WithCode("email_validation")
  .WithErrors(new []
  {
    new ResultError(
      message: "The email host is not allowed",
      code: "invalid_email_host")
  });

// or use the short syntax
var failedResult = Result.Failure()
  .WithMessage("The provided email is not valid")
  .WithCode("email_validation")
  .WithErrors("The email host is not allowed", "invalid_email_host");

If you want to encapsulate an exception, you can do the following:

public Result DoSomeWork()
{
  try
  {
    // your code goes here
    return Result.Success();
  }
  catch(Exception ex)
  {
    return Result.Failure()
      .WithMessage("An internal exception has been thrown")
      .WithCode(ResultCode.OperationFailedException)
      .WithError(ex);
  }
}

Or you can use a predefined method to convert the exception to a result object:

public Result DoSomeWork()
{
  try
  {
    // your code goes here
    return Result.Success();
  }
  catch(Exception ex)
  {
    return ex.ToResult();
  }
}

For more details on working with exceptions, check out our wiki page.

What about logging? By default, if you create a failed result, a LogTraceCode will be generated, and you can include this tracing code in your logs to track the errors:

public Result DoSomeWork()
{
  try
  {
    // your code goes here
    return Result.Success();
  }
  catch(Exception ex)
  {
    var result = ex.ToResult();

    _logger.LogError(ex, "exception {@info}", new
    {
      LogTraceCode = result.LogTraceCode
      // + your metadata about the error
    });

    return result;
  }
}

What about checking your method execution status:

var result = DoSomeWork();

// you can use IsSuccess() or IsFailure()
if (result.IsSuccess()) {
  Console.WriteLine("Operation succeeded");
}

if (result.IsFailure()) {
  Console.WriteLine("Operation failed");
}

// or you can use the Match extension
result.Match(
  // the action to run on success
  onSuccess: result => {
    Console.WriteLine("Executed if result has a success status");
  },
  // the action to run on failure
  onFailure: result => {
    Console.WriteLine("Executed if result has a failure status");
  });

// you can also return a value
var output = result.Match(
  // the func to run on success
  onSuccess: result => {
    Console.WriteLine("Executed if result has a success status");
    return "test";
  },
  // the func to run on failure
  onFailure: result => {
    Console.WriteLine("Executed if result has a failure status");
    return "test";
  });

you can configure the behavior of the Result object using the central configuration method:

Result.Configure(config => {
  // here goes the configuration
});

For more details, check out the Wiki page.


❀️ Contributing & Support

Star ⭐ the repo to support the project. Share your feedback, file issues, or send PRs. Find more examples, documentation, and usage tips in the Wiki and samples folder.

πŸ“ Copyright

Copyright Β© Youssef SELLAMI. See LICENSE for details.

TL;DR

Result.NET is your lightweight, intuitive solution for safer error handling in .NET. Install it, wrap your results, add context, and handle outcomes cleanly β€” no more exceptions or failed methods without explanation.

About

Result.Net provides a result object to be used as a wrapper over operations execution results to indicate success or failure, instead of throwing exceptions or returning false without explanation.

Topics

Resources

License

Stars

Watchers

Forks