Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,34 @@ var result = await FailOr.Success(10)
});
```

### Map safely with `Try`

Use `Try` when the next step should only run after success, but thrown exceptions should become failures instead of escaping the pipeline.

```csharp
using FailOr;

var result = FailOr.Success("42")
.Try(value => int.Parse(value));

if (result.IsFailure)
{
var failure = (Failures.Exceptional)result.Failures[0];
Console.WriteLine(failure.Exception.Message);
}
```

You can also translate the exception into a custom repo-native result:

```csharp
using FailOr;

var result = FailOr.Success("42x")
.Try(
value => int.Parse(value),
exception => Failure.General($"Mapping failed: {exception.Message}"));
```

### Run success-side effects with `ThenDo`

Use `ThenDo` when you want to observe a success without changing the flowing result.
Expand Down
58 changes: 57 additions & 1 deletion docs/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,61 @@ var result = await FailOr.Success(10)
.ThenAsync(async x => await GetAdjustedValueAsync(x));
```

### Map a success value with exception handling

```csharp
public FailOr<TResult> Try<TResult>(Func<TSource, TResult> map)
```

Intent:
Transform a success value while converting thrown exceptions to `Failure.Exceptional(...)`.

Example:

```csharp
var result = FailOr.Success("42")
.Try(int.Parse);
```

### Map a success value with custom exception handling

```csharp
public FailOr<TResult> Try<TResult>(
Func<TSource, TResult> map,
Func<Exception, FailOr<TResult>> onException)
```

Intent:
Transform a success value while projecting thrown exceptions into a custom `FailOr<TResult>`.

Example:

```csharp
var result = FailOr.Success("42x")
.Try(
int.Parse,
exception => Failure.General($"Mapping failed: {exception.Message}"));
```

### Map asynchronously with exception handling

```csharp
public Task<FailOr<TResult>> TryAsync<TResult>(Func<TSource, Task<TResult>> mapAsync)
public Task<FailOr<TResult>> TryAsync<TResult>(
Func<TSource, Task<TResult>> mapAsync,
Func<Exception, FailOr<TResult>> onException)
```

Intent:
Transform a success value with an asynchronous operation while converting thrown exceptions to either `Failure.Exceptional(...)` or a custom projected result.

Example:

```csharp
var result = await FailOr.Success("42")
.TryAsync(value => ParseNumberAsync(value));
```

### Bind asynchronously

```csharp
Expand Down Expand Up @@ -551,7 +606,7 @@ var result = FailOr.Zip(

## Task-Wrapped Result Extensions

The library also provides the same `Then`, `ThenAsync`, `ThenDo`, `ThenDoAsync`, `IfFailThen`, `IfFailThenAsync`, `Match`, `MatchAsync`, `MatchFirst`, and `MatchFirstAsync` APIs for:
The library also provides the same `Then`, `ThenAsync`, `Try`, `TryAsync`, `ThenDo`, `ThenDoAsync`, `IfFailThen`, `IfFailThenAsync`, `Match`, `MatchAsync`, `MatchFirst`, and `MatchFirstAsync` APIs for:

```csharp
Task<FailOr<T>>
Expand Down Expand Up @@ -602,6 +657,7 @@ The current API validates a few important invalid states:
- `UnsafeUnwrap` throws `InvalidOperationException` when the result is failed.
- Async delegate-based APIs throw `ArgumentNullException` when the delegate itself is `null`.
- Async delegate-based APIs also throw `ArgumentNullException` when the selected delegate returns a `null` task.
- `Try` and `TryAsync` convert exceptions thrown by mapping delegates into `Failure.Exceptional(...)` unless you provide a custom exception projection.

## Choosing The Right API

Expand Down
Loading