REslava.Result goes beyond basic Result handling with advanced functional programming patterns that enable type-safe, expressive code. These patterns help you eliminate null reference exceptions, handle complex state machines, and create maintainable, predictable code.
API responses that can be success or specific error types
Parsing operations with multiple valid result types
Configuration values with different possible types
State machines with two distinct states
🚀 Basic Usage
// CreationOneOf<Error,User>result=GetUserFromApi(id);// Pattern matchingreturnresult.Match(case1:error=>HandleError(error),case2:user=>ProcessUser(user));// Functional operationsOneOf<Error,UserDto>dto=result.MapT2(user=>user.ToDto()).BindT2(dto=>ValidateDto(dto));// Switch for side effectsresult.Switch(case1:error=>LogError(error),case2:user=>AuditUserAccess(user));
📚 Complete API Reference
Constructor Methods
OneOf<T1, T2>.FromT1(T1 value) - Create with T1 value
OneOf<T1, T2>.FromT2(T2 value) - Create with T2 value
ToOneOfCustom<T1, T2>(this Result<T2> result, Func<IReason, T1> errorMapper) - Custom Result to OneOf
Pipeline Extensions - Mixed Workflows
🎯 When to Use Pipeline Extensions
Complex business logic requiring multiple pattern transformations
API layering where different layers use different patterns
Data processing pipelines with multiple validation steps
Error handling transformations between different error types
🚀 Real-World Scenarios
// Scenario 1: API → Business → Database pipelineOneOf<ApiError,User>apiResult=GetUserFromApi(1);// Transform to Result for business logicResult<UserDto>businessResult=apiResult.SelectToResult(user=>user.ToDto(),error=>newError($"API Error: {error.Message}"));// Transform back to OneOf for database layerOneOf<DbError,UserDto>dbResult=businessResult.ToOneOfCustom(reason=>newDbError(reason.Message));// Scenario 2: Mixed validation pipelineOneOf<ValidationError,User>validationResult=ValidateUser(user);Result<User>businessResult=validationResult.SelectToResult(user=>user,error=>newError($"Validation failed: {error.Message}"));Result<ProcessedUser>processedResult=businessResult.BindToResult(user=>ProcessUser(user));// Scenario 3: Error type transformationOneOf<string,User>legacyResult=GetLegacyUser(id);OneOf<ApiError,User>modernResult=legacyResult.SelectToResult(user=>user,error=>newApiError(error,500)).ToOneOf(error=>error);
Migration Guide
🔄 From Exceptions to Result Pattern
// Before: Exception-basedtry{Useruser=GetUser(id);returnProcessUser(user);}catch(NotFoundExceptionex){returnHandleNotFound(ex);}catch(ValidationExceptionex){returnHandleValidation(ex);}// After: Result patternResult<User>userResult=GetUser(id);returnuserResult.Match(error=>errorswitch{NotFoundException=>HandleNotFound(error),ValidationException=>HandleValidation(error),_=>Result<User>.Fail("Unknown error")},user=>ProcessUser(user));
🔄 From Result to OneOf
// Before: Result patternResult<User>result=GetUser(id);if(result.IsSuccess){returnProcessUser(result.Value);}else{returnHandleError(result.Errors);}// After: OneOf patternOneOf<Error,User>oneOf=result.ToOneOf(error=>newError(error.Message));returnoneOf.Match(error=>HandleError(error),user=>ProcessUser(user));
// Good: Maybe for optional, OneOf for typed errorsMaybe<Config>config=GetConfig();OneOf<ValidationError,ProcessedConfig>processed=config.Select(c=>ValidateConfig(c)).ValueOrDefault(OneOf<ValidationError,ProcessedConfig>.FromT1(newValidationError("Config not found")));// Good: Result for business logic, OneOf for API layerResult<BusinessResult>business=ProcessBusiness(data);OneOf<ApiError,BusinessResult>api=business.ToOneOf(error=>newApiError(error.Message,400));
❌ Anti-Patterns
// Avoid: OneOf with too many typesOneOf<Error,User,Admin,Guest,System>user=GetUser(id);// Better: Use specific types or state pattern// Avoid: Maybe when you need error detailsMaybe<User>user=GetUser(id);// Lost error information// Better: Use OneOf<Error, User>// Avoid: Mixing patterns unnecessarilyResult<OneOf<Error,User>>complex=GetUser(id);// Better: Choose one pattern consistently
Performance Considerations
📊 Benchmarks
Operation
Maybe\
OneOf\
OneOf\
Result\
Creation
~2ns
~3ns
~4ns
~2ns
Pattern Match
~5ns
~7ns
~9ns
~6ns
Transformation
~8ns
~10ns
~12ns
~8ns
🚀 Optimization Tips
Prefer struct patterns for performance-critical code
Use specific types instead of string/object when possible
Avoid deep nesting of pattern matches
Consider inline functions for simple transformations
Profile your specific use case - patterns have different characteristics
🎯 Memory Allocation
Maybe\: Zero allocation for None, boxed for Some with structs
OneOf\: Single allocation, stores discriminator + value
OneOf\: Single allocation, larger discriminator
Result\: Similar to OneOf, optimized for success cases