Result is a contract, usually in the form of IResult.
An IResult has two properties:
Ok: Was the call a success?Reason: Usually ignored whenOk, contains the reason for the failure when notOk
There's also an IResult<T>, which gets an extra property.
Value: Values should only be trusted when the result isOk(thinkTryParse)!
IResults are constructed using the following helper methods:
Result.Success(): Returns anIResultwhereOkistrueResult.Success(T value): Same as above, but returnsIResult<T>withValuesetResult.Failure(string reason, [string.Format params]): Don't be lazy and passnull. No one likes empty errors!Result.Failure(Exception ex): Uses the innermostInnerException'sMessage(useful in catch blocks of course!)
out isn't always an option. Asynchronous code doesn't play well with out parameters. You can't even use an await on a method with an out parameter!
So how do you associate success or failure with Tasks? A Task<X> can't return a Task<Y> when it fails. The only way you communicate failure is to throw an exception, which Microsoft says you shouldn't do (tl;dr exceptions are slow!), and check the task's TaskStatus (or IsFaulted or IsCanceled, depends on what type of exception stopped the task).
So what do you use when out isn't allowed and exceptions are slow? This is the hole Result fills. As a result, methods returning IResult should never throw an exception. You can prefix any IResult method names with Try to emphasize this.
Of course!
PM> Install-Package Result
That's all there is to it. Happy (now faster, more success/failure aware) async coding!