Class ResultLinqExtensions
- Namespace
- FunctionalDdd
- Assembly
- FunctionalDdd.RailwayOrientedProgramming.dll
Provides LINQ query expression support for Result types, enabling C# query syntax for functional operations.
public static class ResultLinqExtensions
- Inheritance
-
ResultLinqExtensions
- Inherited Members
Examples
// Using LINQ query syntax with Result
var result = from firstName in FirstName.TryCreate(firstNameInput)
from lastName in LastName.TryCreate(lastNameInput)
from email in EmailAddress.TryCreate(emailInput)
where email.Value.EndsWith("@company.com")
select new User(firstName, lastName, email);
// This is equivalent to:
var result2 = FirstName.TryCreate(firstNameInput)
.Bind(firstName => LastName.TryCreate(lastNameInput)
.Bind(lastName => EmailAddress.TryCreate(emailInput)
.Ensure(email => email.Value.EndsWith("@company.com"),
Error.Validation("Must be company email"))
.Map(email => new User(firstName, lastName, email))));
Remarks
These extension methods allow you to use LINQ query syntax (from, select, where) with Result types, making functional composition more readable and familiar to C# developers.
The mapping is: - Select maps to Map<TIn, TOut>(Result<TIn>, Func<TIn, TOut>) - SelectMany maps to Bind<TValue, TResult>(Result<TValue>, Func<TValue, Result<TResult>>) - Where maps to Ensure<TValue>(Result<TValue>, Func<TValue, bool>, Error)
Methods
SelectMany<TSource, TCollection, TResult>(Result<TSource>, Func<TSource, Result<TCollection>>, Func<TSource, TCollection, TResult>)
Projects each value of a Result to a new Result and flattens the result (LINQ SelectMany operation). Enables composition of multiple Result-returning operations in LINQ query syntax.
public static Result<TResult> SelectMany<TSource, TCollection, TResult>(this Result<TSource> source, Func<TSource, Result<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
Parameters
sourceResult<TSource>The source result.
collectionSelectorFunc<TSource, Result<TCollection>>A function that returns a Result based on the source value.
resultSelectorFunc<TSource, TCollection, TResult>A function to create the final result from the source and collection values.
Returns
- Result<TResult>
A new Result with the final projected value, or the first failure encountered.
Type Parameters
TSourceThe type of the source value.
TCollectionThe type of the intermediate collection value.
TResultThe type of the final result value.
Remarks
This is the key method that enables LINQ query syntax with multiple 'from' clauses. It performs monadic bind followed by a projection.
Select<TIn, TOut>(Result<TIn>, Func<TIn, TOut>)
Projects the value of a successful Result using a selector function (LINQ Select operation). Maps to Map<TIn, TOut>(Result<TIn>, Func<TIn, TOut>).
public static Result<TOut> Select<TIn, TOut>(this Result<TIn> result, Func<TIn, TOut> selector)
Parameters
resultResult<TIn>The result to project.
selectorFunc<TIn, TOut>The projection function to apply to the value.
Returns
- Result<TOut>
A new Result with the projected value, or the original failure.
Type Parameters
TInThe type of the input value.
TOutThe type of the output value.
Where<TSource>(Result<TSource>, Func<TSource, bool>)
Filters a Result based on a predicate (LINQ Where operation). If the predicate returns false, converts the success Result to a failure.
public static Result<TSource> Where<TSource>(this Result<TSource> source, Func<TSource, bool> predicate)
Parameters
sourceResult<TSource>The result to filter.
predicateFunc<TSource, bool>The predicate to test the value against.
Returns
- Result<TSource>
The original success Result if the predicate is true; otherwise a failure Result with a generic error.
Type Parameters
TSourceThe type of the source value.
Examples
// Using Where in query syntax (generic error)
var result = from user in GetUser(id)
where user.IsActive
select user;
// Better: Use Ensure for custom error
var betterResult = GetUser(id)
.Ensure(u => u.IsActive, Error.Domain("User is not active"));
Remarks
This method returns a generic "filtered out" error message. For more meaningful error messages, use Ensure<TValue>(Result<TValue>, Func<TValue, bool>, Error) directly instead.