Add Result pattern for standardized error handling

Implement Result<T> and Result classes to provide type-safe,
functional error handling throughout the application. This
eliminates the need for exceptions as control flow and provides
a consistent way to communicate success/failure.

Features:
- Result<T> for operations that return values
- Result for operations without return values
- Map() method for functional composition
- IsSuccess/IsFailure properties for easy checking

This pattern enables cleaner service contracts and eliminates
the need for out parameters and exception handling boilerplate.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
AJ
2025-11-18 17:43:12 -05:00
parent c7c841acab
commit 9abd00487b

96
CutList/Common/Result.cs Normal file
View File

@@ -0,0 +1,96 @@
using System;
namespace CutList.Common
{
/// <summary>
/// Represents the result of an operation that can either succeed with a value or fail with an error.
/// Implements the Result pattern for standardized error handling.
/// </summary>
/// <typeparam name="T">The type of the success value</typeparam>
public class Result<T>
{
private Result(T value, bool isSuccess, string error)
{
Value = value;
IsSuccess = isSuccess;
Error = error;
}
public T Value { get; }
public bool IsSuccess { get; }
public bool IsFailure => !IsSuccess;
public string Error { get; }
/// <summary>
/// Creates a successful result with a value.
/// </summary>
public static Result<T> Success(T value)
{
return new Result<T>(value, true, null);
}
/// <summary>
/// Creates a failed result with an error message.
/// </summary>
public static Result<T> Failure(string error)
{
if (string.IsNullOrWhiteSpace(error))
throw new ArgumentException("Error message cannot be empty", nameof(error));
return new Result<T>(default(T), false, error);
}
/// <summary>
/// Maps the success value to a new result type.
/// </summary>
public Result<TNew> Map<TNew>(Func<T, TNew> mapper)
{
if (IsFailure)
return Result<TNew>.Failure(Error);
try
{
return Result<TNew>.Success(mapper(Value));
}
catch (Exception ex)
{
return Result<TNew>.Failure(ex.Message);
}
}
}
/// <summary>
/// Represents the result of an operation that can succeed or fail without a return value.
/// </summary>
public class Result
{
protected Result(bool isSuccess, string error)
{
IsSuccess = isSuccess;
Error = error;
}
public bool IsSuccess { get; }
public bool IsFailure => !IsSuccess;
public string Error { get; }
/// <summary>
/// Creates a successful result.
/// </summary>
public static Result Success()
{
return new Result(true, null);
}
/// <summary>
/// Creates a failed result with an error message.
/// </summary>
public static Result Failure(string error)
{
if (string.IsNullOrWhiteSpace(error))
throw new ArgumentException("Error message cannot be empty", nameof(error));
return new Result(false, error);
}
}
}