Map & Bind
Map — Transform the Value
Map applies a function to the inner value if it is a success. Errors pass through unchanged — you stay on the “happy rail”.
// Sync
ApiResult<string> title = ApiResult.Ok(todo)
.Map(t => t.Title.ToUpperInvariant());
// Async
ApiResult<string> title = await ApiResult.Ok(todo)
.MapAsync(async t => await EnrichTitleAsync(t.Title));
Use Map when transforming data without introducing new failure cases.
Bind — Chain Operations
Bind (flatMap) sequences operations where each step can itself fail. It unwraps the value and passes it to a function that returns a new ApiResult<TResult>, preventing nested ApiResult<ApiResult<T>>.
// Sync
ApiResult<string> result = ApiResult.Ok(42)
.Bind(id => id > 0
? ApiResult.Ok(id.ToString())
: ApiResult.HttpFail<string>(HttpStatusCode.BadRequest, "Invalid id"));
// Async
ApiResult<string> result = await ApiResult.Ok(42)
.BindAsync(async id => await FetchUserAsync(id));
Use Bind when the next operation can also fail.
Map vs Bind — at a glance
| Input | Output | |
|---|---|---|
Map |
T |
TResult (transform only) |
Bind |
T |
ApiResult<TResult> (can fail) |