private void TransformingErrorWithMapError() { ITry <int, NetworkOperationError> number = Api.GetNumber(); // You can use MapError to map for example from exception to another type you use to represent errors. Or map to logging messages. ITry <int, string> flooredMultiplicationResult = number.MapError(e => e.ToString()); }
public bool Equals(ITry <T> other) { return (other != null && !other.IsValid && _error.Equals(other.Error)); }
/// <summary> /// Maps the successful result to a new try. /// </summary> public static ITry <B, E> FlatMap <A, E, B>(this ITry <A, E> t, Func <A, ITry <B, E> > f) { return(t.Match( s => f(s), e => Try.Error <B, E>(e) )); }
private static void CreatingTryDirectly() { // Note that we explicitly specify types of variables in the following examples. However, in practice, we use var. // Creates an ITry with successful result while specifying type of an error. ITry <int, NetworkOperationError> success = Try.Success <int, NetworkOperationError>(42); // Creates an ITry with erroneous result while specifying type of a success. ITry <int, NetworkOperationError> error = Try.Error <int, NetworkOperationError>(NetworkOperationError.NetworkIssues); // Creating a successful ITry while specifying type of an error. ITry <int, Exception> successTry = 42.ToTry < int, Exception > (); // Creating an erronous ITry directly from exception while specifying type of a success. ITry <int, Exception> errorTry = new Exception().ToTry <int, Exception>(); // Converting an option to try. var option = Option.Empty <int>(); ITry <int, Exception> tryFromOption = option.ToTry(_ => new Exception("No value was provided in the option.")); ITry <int, string> tryFromOptionWithErrorType = option.ToTry(_ => "No value was provided in the option."); // Generally collections are recommended for validations. // It is easy to aggregate validations of multiple values into one ITry of the whole object. // And then you either get the successfully parsed object or you have the list of errors. ITry <int, IEnumerable <string> > validationRepresentation = option.ToTry(_ => new[] { "No valid value was provided in the option." }); }
private void AggregatingCollectionOfTries(int numberCount) { IEnumerable <ITry <int, NetworkOperationError> > numbers = Enumerable.Range(0, numberCount).Select(_ => Api.GetNumber()); // Contains all the numbers if their retrieval succeeded. Or all the errors from the ones that failed. Success results are lost in such case. ITry <IEnumerable <int>, IEnumerable <NetworkOperationError> > combinedResult = Try.Aggregate(numbers); }
static void Main(string[] args) { ITry ThisMeaning = (ITry) new Meaning(); // This works ThisMeaning.foo(); ThisMeaning.Dispose(); // The method is available }
public static ITry <T> Where <T>(this ITry <T> value, Func <T, bool> evaluator, Func <Unit, Exception> error) { return(value.FlatMap(v => evaluator(v).ToTry( t => v, f => error(Unit.Value) ))); }
/// <summary> /// If the successful result passes the predicate, returns the original try. Otherwise returns erroneous try with the specified result. /// </summary> public static ITry <A, E> Where <A, E>(this ITry <A, E> t, Func <A, bool> predicate, Func <Unit, E> otherwise) { return(t.FlatMap(a => predicate(a).Match( _ => t, _ => Try.Error <A, E>(otherwise(Unit.Value)) ))); }
/// <summary> /// If the successful result passes the predicate, returns the original try. Otherwise returns erroneous try with the specified result. /// </summary> public static ITry <A, IEnumerable <E> > Where <A, E>(this ITry <A, IEnumerable <E> > t, Func <A, bool> predicate, Func <Unit, E> otherwise) { return(t.FlatMap(a => predicate(a).Match( _ => t, _ => Try.Error <A, IEnumerable <E> >(new[] { otherwise(Unit.Value) }) ))); }
/// Causes this promise to be completed with <c>result</c>. public void Complete(ITry <T> result) { if (_result != null) { throw new InvalidOperationException("Already completed"); } _result = result; if (_onComplete != null) { try { var lners = _onComplete.GetInvocationList(); List <Exception> errors = null; foreach (Action <ITry <T> > lner in lners) { try { lner(_result); } catch (Exception e) { if (errors == null) { errors = new List <Exception>(); } errors.Add(e); } } if (errors != null) { throw new AggregateException(errors); } } finally { _onComplete = null; } } }
public bool Equals(ITry <T> other) { return (other != null && other.IsValid && _value.Equals(other.Value)); }
public static ITry <T, INonEmptyEnumerable <E> > Where <T, E>(this ITry <T, INonEmptyEnumerable <E> > value, Func <T, bool> evaluator, Func <Unit, E> error) { return(value.FlatMap(v => evaluator(v).ToTry( t => v, f => error(Unit.Value).ToEnumerable() ))); }
/// <summary> /// If the result is success, returns it. Otherwise throws the result of the otherwise function. /// </summary> public static A Get <A, E>(this ITry <A, E> t, Func <E, Exception> otherwise) { return(t.Match( s => s, e => throw otherwise(e) )); }
public override void WriteJson( JsonWriter writer, ITry <object> value, JsonSerializer serializer) => value .Match( _ => FromObject(_, serializer), _ => FromObject(_, serializer)) .WriteTo(writer);
private IOption <UserMessage> ProcessResult(ITry <ShoppingListWithItems, CookRecipeError> result) => result.Match( s => UpdateShoppingList(s).Pipe(_ => Option.Empty <UserMessage>()), e => Option.Create(e.Match( CookRecipeError.NotEnoughFoodstuffsInShoppingList, _ => UserMessages.NotEnoughFoodstuffsInShoppingList() )) );
private void HandlingNestedTriesWithFlatMap() { ITry <int, NetworkOperationError> number = Api.GetNumber(); ITry <ITry <int, NetworkOperationError>, NetworkOperationError> doubleNumber = number.Map(r => Api.DoubleNumber(r)); // This try succeeds only if both tries succeed. However the second lambda is only executed in case the first try is successful. ITry <int, NetworkOperationError> doubleNumberFlattened = number.FlatMap(r => Api.DoubleNumber(r)); }
/// <summary> /// Aggregates the tries using the specified function if all of them are successful. Otherwise aggregates all errors into error result by concatenation. /// </summary> public static ITry <R, IEnumerable <E> > Aggregate <A1, A2, A3, A4, R, E>(ITry <A1, IEnumerable <E> > t1, ITry <A2, IEnumerable <E> > t2, ITry <A3, IEnumerable <E> > t3, ITry <A4, IEnumerable <E> > t4, Func <A1, A2, A3, A4, R> success) { return(Aggregate( t1, t2, t3, t4, success: (s1, s2, s3, s4) => Success <R, IEnumerable <E> >(success(s1, s2, s3, s4)), error: errors => Error <R, IEnumerable <E> >(errors.SelectMany(e => e).ToList()) )); }
private UserActionResult ToUserActionResult(ITry <Unit, SignInError> t) => t.Match( s => UserActionResult.Success(), e => e.Match( SignInError.InvalidCredentials, _ => UserActionResult.Error(UserMessages.InvalidCredentials()), SignInError.NoConnection, _ => UserActionResult.Error(UserMessages.NoConnection()) ) );
/// <summary> /// Aggregates the tries using the specified function if all of them are successful. Otherwise aggregates all errors into error result by concatenation. /// </summary> public static ITry <R, IEnumerable <E> > Aggregate <A1, A2, A3, R, E>(ITry <A1, E> t1, ITry <A2, E> t2, ITry <A3, E> t3, Func <A1, A2, A3, R> success) { return(Aggregate( t1, t2, t3, success: (s1, s2, s3) => Success <R, IEnumerable <E> >(success(s1, s2, s3)), error: errors => Error <R, IEnumerable <E> >(errors) )); }
public static ITry <T> Do <T>(this ITry <T> original, Action <T> execute) { if (original is Success <T> success) { execute(success.Value); } return(original); }
/// <summary> /// Maps the error result to a new try. /// </summary> public static ITry <B, F> FlatMapError <A, E, B, F>(this ITry <A, E> t, Func <E, ITry <B, F> > f) where A : B where E : F { return(t.Match( s => Try.Success <B, F>(s), e => f(e) )); }
public static ITry <T> DoError <T>(this ITry <T> original, Action <string> execute) { if (original is Failure <T> error) { execute(error.Message); } return(original); }
private UserActionResult ToUserActionResult(ITry <Unit, SignUpError[]> t) => t.Match( s => UserActionResult.Success(), e => e.First().Match( SignUpError.NoConnection, _ => UserActionResult.Error(UserMessages.NoConnection()), SignUpError.InvalidEmail, _ => Email.Invalidate().Pipe(u => UserActionResult.Error()), SignUpError.PasswordTooShort, _ => Password.Invalidate().Pipe(u => UserActionResult.Error()), SignUpError.AccountAlreadyExists, _ => UserActionResult.Error(UserMessages.AccountAlreadyExists()) ) );
public static Tuple <bool, Exception> MatchFailure <T>(ITry <T> candidate) { var fail = candidate as Failure <T>; if (fail != null) { return(Tuple.Create(true, fail.GetException())); } return(Tuple.Create <bool, Exception>(false, null)); }
/// <summary> /// Return the first success otherwise concatenate the error messages of both failures. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="original"></param> /// <param name="fn"></param> /// <returns></returns> public static ITry <T> SelectFirstSuccess <T>(this ITry <T> original, Func <ITry <T> > fn) => original.Match( success: (val) => original, failure: (firstError) => fn().Let( secondResult => secondResult.Match( success: (_) => secondResult, failure: (secondError) => Try.Failure <T>(String.Concat(firstError, ", ", secondError)) ) ) );
/// <summary> /// Aggregates the tries using the specified function if all of them are successful. Otherwise aggregates the errors by the specified function. /// </summary> public static R Aggregate <A1, A2, A3, A4, A5, A6, E, R>(ITry <A1, E> t1, ITry <A2, E> t2, ITry <A3, E> t3, ITry <A4, E> t4, ITry <A5, E> t5, ITry <A6, E> t6, Func <A1, A2, A3, A4, A5, A6, R> success, Func <IEnumerable <E>, R> error) { if (t1.IsSuccess && t2.IsSuccess && t3.IsSuccess && t4.IsSuccess && t5.IsSuccess && t6.IsSuccess) { return(success(t1.Success.Get(), t2.Success.Get(), t3.Success.Get(), t4.Success.Get(), t5.Success.Get(), t6.Success.Get())); } var errors = new[] { t1.Error, t2.Error, t3.Error, t4.Error, t5.Error, t6.Error }; return(error(errors.Flatten().ToList())); }
/// <summary> /// Aggregates the tries using the specified function if all of them are successful. Otherwise aggregates the errors by the specified function. /// </summary> public static R Aggregate <A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, E, R>(ITry <A1, E> t1, ITry <A2, E> t2, ITry <A3, E> t3, ITry <A4, E> t4, ITry <A5, E> t5, ITry <A6, E> t6, ITry <A7, E> t7, ITry <A8, E> t8, ITry <A9, E> t9, ITry <A10, E> t10, Func <A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, R> success, Func <IEnumerable <E>, R> error) { if (t1.IsSuccess && t2.IsSuccess && t3.IsSuccess && t4.IsSuccess && t5.IsSuccess && t6.IsSuccess && t7.IsSuccess && t8.IsSuccess && t9.IsSuccess && t10.IsSuccess) { return(success(t1.Success.Get(), t2.Success.Get(), t3.Success.Get(), t4.Success.Get(), t5.Success.Get(), t6.Success.Get(), t7.Success.Get(), t8.Success.Get(), t9.Success.Get(), t10.Success.Get())); } var errors = new[] { t1.Error, t2.Error, t3.Error, t4.Error, t5.Error, t6.Error, t7.Error, t8.Error, t9.Error, t10.Error }; return(error(errors.Flatten().ToList())); }
/// <summary> /// Aggregates the tries using the specified function if all of them are successful. Otherwise aggregates the errors by the specified function. /// </summary> public static R Aggregate <A1, A2, E, R>(ITry <A1, E> t1, ITry <A2, E> t2, Func <A1, A2, R> success, Func <IEnumerable <E>, R> error) { if (t1.IsSuccess && t2.IsSuccess) { return(success(t1.Success.Get(), t2.Success.Get())); } var errors = new[] { t1.Error, t2.Error }; return(error(errors.Flatten().ToList())); }
/// <summary> /// If the result is success, returns it. Otherwise throws the exception. /// </summary> public static A Get <A, E>(this ITry <A, E> t) where E : Exception { return(t.Match( s => s, e => { ExceptionDispatchInfo.Capture(e).Throw(); return default; } )); }
public static void HandlingExceptionsWithCatch(decimal number, decimal divisor) { // Catches any exception and stores the single exception into the try. // This is useful for handling individual errors, but cannot be aggregated. ITry <decimal, Exception> divisionHandlingAllExceptions = Try.Catch <decimal, Exception>(_ => number / divisor); // Only catches a specific exception. Notice that the error type is the specific type of exception, not a collection of exceptions. ITry <decimal, DivideByZeroException> divisionHandlingDividingByZero = Try.Catch <decimal, DivideByZeroException>(_ => number / divisor); // Catch also has an overload which allows recovering in case of exception. Serves as standard try/catch, but returns a value. decimal divisionResult = Try.Catch <decimal, DivideByZeroException>( _ => number / divisor, exception => 0 ); }