Result Type
Result<T> is similar to std::result data type in Rust programming language and allows to handle method call errors without try-catch
block. The value can contain actual result returned from method or error in the form of exception.
.NET library provides TryInvoke
extension methods to return Result<T>
from popular delegate types such as Func, Converter. The type behaves like monad and the pipeline of calls can be constructed.
using DotNext;
Func<string, int> parser = int.Parse;
Result<int> result = parser.TryInvoke("42");
if (result) //successful
{
var i = (int)result;
}
Value
property can be used to extract the value of the result, or throws the exception if the result is not available.
using DotNext;
Func<string, int> parser = int.Parse;
Result<int> result = parser.TryInvoke("42");
int value = result.Value; // may throw
Error
property can be used to inspect the underlying exception:
using DotNext;
Func<string, int> parser = int.Parse;
Result<int> result = parser.TryInvoke("42");
if (result.IsSuccessful) //successful
{
var i = result.ValueOrDefault;
}
else
{
Exception e = result.Error;
}
Note
It's not recommended to rethrow the exception by using Error
property. It that case, you lose the information about initial stack trace. If you need to capture the state of the exception or rethrow it, use ExceptionDispatchInfo class.
Result type is paired with Optional data type. Result<T>
can be converted to it implicitly. But conversion loses information about exception:
using DotNext;
Func<string, int> parser = int.Parse;
Optional<int> result = parser.TryInvoke("42");
Custom error codes
Result<T, TError> is an overloaded type that allows to use custom error codes instead of exceptions. The second generic parameter expects enum type that enumerates all possible error codes.
using DotNext;
enum ErrorCode
{
Success = 0,
InvalidInputString,
}
static Result<int, ErrorCode> TryParse(string input) => int.TryParse(input) ? input : new(ErrorCode.InvalidInputString);
Both types are interoperable:
Result<int, ErrorCode> result1 = TryParse("123");
Result<int> result2 = result1;