This library helps you write a C# code in a functional way. It is inspired by the CSharpFunctionalExtensions library, but focuses solely on the Result type.
It uses an ErrorMessage
type for errors, that is not just an error message but also a type, which allows to map, suppress or otherwise handle specific errors, while making sure that creating new error types is not too verbose. The ErrorMessage
also has an optional field Field
for usage with field validation, so that you can correlate an error message to a specific field.
It is an opinionated solution, but I believe it is better then the alternatives:
- simple string: very easy to instantiate but not very versatile
- generic type: can be custom tailored but the types that need to be used get very verbose, the addition af a result itself is already making types comlicated. let's say we want to have
MyType
returned, the type need for a simple return like that might look something like thisTask<Result<MyType, ValidationErrorType>>>
- strictly typed errors, with each error being a separate class: adds the most flexibility, but it needs a lot of code
The failure Result
is not limited to a single error message. The result stores a list of error messages, so that it's possible to, for example, validate object's fields and return all the issues.
It also adds a WarningMessage
type passed with the successful Result
. It is an idea I'm toying with right now, so it might still need a little polish. It allows to create an optional part of the functions chain, while still getting a feedback from that part. It has the same structure as the ErrorMessage
and in fact the list of errors can be downgraded to warnings.
In principle:
- conditions should accept:
- boolean
true/false
- function returning boolean
() => true
. Sometimes with a parameterarg => arg > 0
- a task returning boolean
() => Task.FromResult(true)
orarg => Task.FromResult(arg > 0)
- boolean
- chain methods should accept both sync and async functions
.Map(arg => arg + 1)
.Map(arg => Task.FromResult(arg = 1)
Returns Success or Failure result depending on the value of the condition parameter
var condition = true;
//just the Result
Result result = Result.Create(condition, new ErrorMessage("errorType", "Error message"));
//or a ValueResult
Result<string> valueResult = Result.Create(condition, "some value", new ErrorMessage("errorType", "Error message"));
Result result = Result.Success();
Result<string> valueResult = Result.Success("some value);
Result result = Result.Failure(new ErrorMessage("errorType", "Error message"));
Result<SomeType> valueResult = Result.Failure<SomeType>(new ErrorMessage("errorType", "Error message"));
SomeType? variable;
Result<SomeType> valueResult = Result.Ensure.HasValue(variable);
Result result1;
Result result2;
Result<int> valueResult1;
Result<int> valueResult2;
//if there are multiple types of results combined, only the Result will be returned
Result result = Result.Combine(result1, result2, result3);
//when possible (all the combined Results have the same type) a list of received values will be returned
Result<IEnumberable<int>> valueResult = Result.Combine(result1, result2, result3);
On Success, performs mutating action
On Success, if the condition is met, performs non mutating action
On Success, performs non mutating action
On Success, if the condition is met, performs non mutating action
On either Success or Failure resolves Result into a single value
On Success, performs a non essential action (Result of that action will not change the Result of the mine pipeline, instead, it's result will be converted into a warning)
On Failure, it will perform an action
Checks a condition and changes the Result accordingly
On Failure, throws an exception
Removes errors of a specified type
Removes errors of a specified type. Allows a callback. The callback can be used to infer a return value.
Removes warnings of a specified type. Allows a callback.
Adds warning.
Adds warning if the condition is met