Skip to content

Try And TryAsync Type

Zeid Youssefzadeh edited this page Feb 24, 2025 · 2 revisions

Overview

The ZeidLab.ToolBox.Results namespace provides a consistent approach for safe error handling and composition of operations in CSharp using Railway-Oriented Programming (ROP) patterns. It offers two primary delegates for structured error handling:

  • Try<TIn> for synchronous operations.
  • TryAsync<TIn> for asynchronous operations.

These delegates enable safe execution of operations with built-in error capturing, making it easier to compose and chain workflows. Wrap all exception-prone code in Try/TryAsync delegates and Use Match() for comprehensive result handling.

API Reference

Method Description Returns
Try<TIn> Sync operation wrapper Result<TIn>
TryAsync<TIn> Async operation wrapper Task<Result<TIn>>
ToAsync() Sync → async conversion TryAsync<TIn>
Try() Safe sync execution Result<TIn>
TryAsync() Safe async execution Task<Result<TIn>>

Usage:

The provided examples highlight how to leverage Try, TryAsync, and extension methods to create resilient workflows, and Safely execute synchronous/asynchronous operations with automatic exception capture.

1. Try Delegate (Synchronous)

Definition:

public delegate Result<TIn> Try<TIn>();

Basic Example: Return Failure directly if divisor is 0 with exception

// define a synchronous operation
Try<int> divide = () => {
    int dividend = 10;
    int divisor = 0;
    if (divisor == 0)
        return Result.Failure<int>(new DivideByZeroException("Cannot divide by zero"));
    return Result.Success(dividend / divisor);
};
// execute the operation
Result<int> result = divide.Try();
result.Match(
    success: value => Console.WriteLine($"Result: {value}"), // skipped
    failure: error => Console.WriteLine($"Error: {error.Message}") // executed
); // Output: Error: Cannot divide by zero

Advanced Example: Capture exceptions from int.Parse

// define a synchronous operation
Try<int> parseNumber = () => Result.Success(int.Parse("invalid"));
// execute the operation
Result<int> result = parseNumber.Try();
Console.WriteLine(result.IsFailure); // True (FormatException captured)

2. TryAsync Delegate (Asynchronous)

Definition:

public delegate Task<Result<TIn>> TryAsync<TIn>();

Example: Encapsulate asynchronous operations and automatically handle exceptions.

// define an asynchronous operation
TryAsync<string> fetchData = async () => {
    using var client = new HttpClient();
    var response = await client.GetStringAsync("https://api.example.com/data");
    return Result.Success(response);
};
// execute the operation
Result<string> result = await fetchData.TryAsync();
result.Match(
    success: data => Console.WriteLine($"Data: {data}"),
    failure: error => Console.WriteLine($"Error: {error.Message}")
);

Example: Converting Sync to Async

// define a synchronous operation
Try<int> getValue = () => Result.Success(42);
// convert to an asynchronous operation and execute
Result<int> asyncResult = await getValue.ToAsync().TryAsync();
asyncResult.Match(
    success: value => Console.WriteLine($"Value: {value}"), // executed
    failure: error => Console.WriteLine($"Error: {error.Message}") // skipped
); // output: Value: 42

Extension Methods

Keep in mind that these delegates are not going to be executed on their own. The extension methods use .Try()/.TryAsync() to execute the delegates behind the scenes. So If you want to just get the result of an operation, you need to use Try()/TryAsync() as well.

Try

Example: Safely executes a synchronous operation and captures exceptions.

// define a synchronous operation
Try<int> divideByZero = () => Result.Success(100 / 0);
// execute the operation
Result<int> result = divideByZero.Try();
Console.WriteLine(result.IsFailure); // True

TryAsync

Example: Safely executes an asynchronous operation and captures exceptions.

// define an asynchronous operation
TryAsync<string> fetchData = async () => {
    using var client = new HttpClient();
    var data = await client.GetStringAsync("https://invalid-url");
    return Result.Success(data);
};
// execute the operation
Result<string> result = await fetchData.TryAsync();
if (result.IsFailure)
    Console.WriteLine("Failed to fetch data");

ToAsync

Example: Converts a synchronous Try operation to an asynchronous TryAsync operation.

// define a synchronous operation
Try<int> parseNumber = () => Result.Success(int.Parse("abc"));
// convert to an asynchronous operation
TryAsync<int> asyncOp = parseNumber.ToAsync();
// execute the asynchronous operation
Result<int> result = await asyncOp.TryAsync();
result.Match(
    success: value => Console.WriteLine($"Parsed: {value}"), // skipped
    failure: error => Console.WriteLine($"Error: {error.Message}") // executed
); // output: Error: FormatException
Clone this wiki locally