🎯 Explicit Error Handling
Exceptions for control flow? Expensive. Hidden. Result pattern makes errors explicit and performant.
Traditional Exception Way
public User GetUser(int id)
{
var user = _db.Users.Find(id);
if (user == null)
throw new NotFoundException("User not found");
if (!user.IsActive)
throw new InvalidOperationException("User inactive");
return user;
}
// Caller has no idea what exceptions to catch
try
{
var user = GetUser(123);
}
catch (Exception ex) // Too broad!
{
// What went wrong?
}
Result Pattern Way
// Result class public class Result{ public bool IsSuccess { get; } public T Value { get; } public string Error { get; } private Result(T value) { IsSuccess = true; Value = value; } private Result(string error) { IsSuccess = false; Error = error; } public static Result Success(T value) => new(value); public static Result Failure(string error) => new(error); } // Usage public Result GetUser(int id) { var user = _db.Users.Find(id); if (user == null) return Result .Failure("User not found"); if (!user.IsActive) return Result .Failure("User inactive"); return Result .Success(user); } // Caller knows exactly what to check var result = GetUser(123); if (result.IsSuccess) { var user = result.Value; // Success path } else { // Handle error Console.WriteLine(result.Error); }
🎯 API Controller Integration
[HttpGet("{id}")]
public IActionResult GetUser(int id)
{
var result = _userService.GetUser(id);
return result.IsSuccess
? Ok(result.Value)
: NotFound(new { error = result.Error });
}
// Clean, explicit, no exceptions
✅ Benefits
- Performance: No exception stack trace generation
- Explicit: Caller must handle success/failure
- Type-safe: Compiler enforces error handling
- Testable: Easy to test both paths
“Switched from exceptions to Result pattern in hot path. Performance improved 40%. Error handling became explicit. Code reviews caught missing error checks at compile time.”
