https://github.com/lucasteles/resulteles
A practical Result data structure implementation for C#
https://github.com/lucasteles/resulteles
csharp dotnet either monad result
Last synced: 8 months ago
JSON representation
A practical Result data structure implementation for C#
- Host: GitHub
- URL: https://github.com/lucasteles/resulteles
- Owner: lucasteles
- License: mit
- Created: 2023-07-05T23:02:35.000Z (about 2 years ago)
- Default Branch: master
- Last Pushed: 2024-04-01T14:20:25.000Z (over 1 year ago)
- Last Synced: 2024-04-27T05:03:22.126Z (over 1 year ago)
- Topics: csharp, dotnet, either, monad, result
- Language: C#
- Homepage:
- Size: 73.2 KB
- Stars: 4
- Watchers: 1
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
[](https://github.com/lucasteles/Resulteles/actions/workflows/ci.yml)
[](https://www.nuget.org/packages/Resulteles)





# Resulteles
**Resulteles is a practical and lightweight library that define and facilitate the use of a `success|failure` data
structure called `Result` (aka `Either`).**## Getting started
[NuGet package](https://www.nuget.org/packages/Resulteles) available:
```ps
$ dotnet add package Resulteles
```### Creating Results
You can create any result using the static methods on `Result`
```csharp
// explicitly
var resultSuccess = Result.Ok(42);
var resultError = Result.Error("Something wrong!");var processResult = Result.Try(() => { return 1; });
var processAsyncResult = Result.TryAsync(async () => { return await Task.FromResult(2); });
```In most of the scenarios you will be using result as a return of a method or function, because of that it
implements implicit convert operators from the generic types, reducing the generic type definition noise```csharp
public Result GetEvenNumber(int number)
{
if (number % 2 is 0)
return number;
else
return $"{number} is not even!";
}
```### Reading Result Value
The `Result` type acts like a blackbox, by default there is no way to just get the typed value mostly because it can be
two things, an `Ok` or an `Error`.```csharp
Result result = GetEvenNumber(2);// return -1 on error
int value1 = result.Match(
n => n,
error => -1
);result.Switch(
n => Console.WriteLine($"the number {n} is even"),
error => Console.WriteLine(error)
);// return 0 on error
var value2 = result.DefaultValue(0);// lazily define the bad case value
var value3 = result.DefaultWith(e => e.Length);// get the value or throw an exeption
var value4 = result.GetValueOrThrow();// try/out pattern
if (result.TryGet(out var ok, out var error))
Console.WriteLine($"the number {ok} is even");
else
Console.WriteLine(error);
```### Operators
Most types you not even need to extract the value, you can just apply functions or combine with other `Result` types:
```csharp
var result1 = Result.Ok(1);// Map the result value only when it is Ok
var result2 = result1.Select(n => n + 1);// map for ok or error case
Result result3 = result1.Select(n => n.ToString(), err => err.Length);// SelectMany / Bind / FlatMamap
// Nested results transformation
Result resultCombined = result1.SelectMany(n => GetEvenNumber(n));// Zip Results together into a tuple
// only resolves as Ok when both are Ok
Result<(int, int), string> resultZip = result1.Zip(result2);// Zip Results together
// only resolves as Ok when both are Ok
Result resultSum = result1.Zip(result2, (a, b) => a + b);// Enumerate result, empty when error, singleton when error (see ToArray() also)
IEnumerable resultEnumerable = result1.AsEnumerable();// LINQ QUERY
// you can use linq query to easily express map and bind// simple map
var result2Linq = from r in result1 select r + 1;// combining multiple results (fail fast at first non ok value)
var resultEvenSum =
from a in GetEvenNumber(2)
from b in GetEvenNumber(4)
from c in GetEvenNumber(6)
select a + b + c;
}
```### Async/Await
This library implements some helpers to seamless deal with async Result code
```csharp
var result = GetEvenNumber(2);// async match overload
int value1 = await result.Match(
async n =>
{
await Task.Delay(n);
return n;
},
_ => -1
);await result.SwitchAsync(
async n => await Console.Out.WriteLineAsync($"the number {n} is even"),
async error => await Console.Error.WriteLineAsync(error)
);// async projection counterparts
Result resultWithDelay = await result.SelectAsync(async n =>
{
await Task.Delay(n);
return n;
});// Transform Result, string> in a awaitable Task>
Result resultWithDelay2 = await result.Select(async n =>
{
await Task.Delay(n);
return n;
}).ToTask();
```# Helper extensions
```csharp
// result collection
var results = new[] { GetEvenNumber(2), GetEvenNumber(3), GetEvenNumber(4) };// filter ok values
IEnumerable okResultsOnly = results.GetOkValues(); // [2,4]// map/reduce based on a result function
var numbers = new[] { 1, 2, 3, 4 };
var calculatedResults = numbers.ChooseResult(x => GetEvenNumber(x)); // [2,4]// group a collection of result into a Result of collection
// collapse to error if any error is in the collection
Result, string> singleResult = results.GroupResults();// Transform Result, string> in a awaitable Task>
Result resultWithDelay2 = await results[0].Select(async n =>
{
await Task.Delay(n);
return n;
}).ToTask();
```# FluentAssertions Extensions
[NuGet package](https://www.nuget.org/packages/Resulteles.FluentAssertions) available:
```ps
$ dotnet add package Resulteles.FluentAssertions
```# Alternatives
- [FluentResults](https://github.com/altmann/FluentResults)
- [language-ext](https://github.com/louthy/language-ext)