### Install LightResults using .NET CLI Source: https://github.com/jscarle/lightresults/blob/develop/docfx/index.md Use this command to add the LightResults package to your .NET project. ```bash dotnet add package LightResults ``` -------------------------------- ### Usage of Generic Error Factory Source: https://context7.com/jscarle/lightresults/llms.txt Demonstrates how to use the generic error factory methods to return specific result types. This example shows creating a `Result` and a plain `Result`. ```csharp // Usage public class UserService { public Result GetUser(int id) { if (id <= 0) return AppError.NotFound>(); // Returns Result return Result.Success(new User { Id = id }); } public Result DeleteUser(int id) { if (id <= 0) return AppError.NotFound(); // Returns Result return Result.Success(); } } var service = new UserService(); var result = service.GetUser(-1); if (result.HasError()) { Console.WriteLine("User not found"); // Output: User not found } public class User { public int Id { get; set; } } ``` -------------------------------- ### Get string representation of a successful result in LightResults Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/performance.md Convert a successful result to its string representation using `ToString()`. This is a standard way to get a summary of the result's state. ```csharp Result.Success().ToString() ``` -------------------------------- ### Define Custom Error Types in C# Source: https://context7.com/jscarle/lightresults/llms.txt Shows how to create custom error classes by inheriting from `Error` for domain-specific error scenarios. Includes examples of `NotFoundError`, `ValidationError`, and `HttpError`. ```csharp using LightResults; using System.Net; // Define custom error types public sealed class NotFoundError : Error { public NotFoundError() : base("The requested resource was not found.") { } public NotFoundError(string resourceName, object id) : base($"{resourceName} with ID '{id}' was not found.", ("ResourceId", id)) { } } public sealed class ValidationError : Error { public ValidationError(string fieldName, string message) : base(message, ("FieldName", fieldName)) { } } public sealed class HttpError : Error { public HttpStatusCode StatusCode { get; } public HttpError(HttpStatusCode statusCode) : base($"HTTP error: {(int)statusCode} {statusCode}", ("StatusCode", statusCode)) { StatusCode = statusCode; } } // Usage var notFoundResult = Result.Failure(new NotFoundError("User", 123)); var validationResult = Result.Failure(new ValidationError("Email", "Invalid email format")); var httpResult = Result.Failure(new HttpError(HttpStatusCode.ServiceUnavailable)); // Check for specific error types if (notFoundResult.IsFailure(out var error) && error is NotFoundError) { Console.WriteLine("Resource was not found!"); } // Use HasError() to check error type if (httpResult.HasError()) { Console.WriteLine("An HTTP error occurred"); } // Get the specific error type with out parameter if (httpResult.HasError(out var httpError)) { Console.WriteLine($"Status code: {httpError.StatusCode}"); } ``` -------------------------------- ### New IsFailure overload to get error Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/breaking-changes.md Retrieve the error details from a result using this overload. ```csharp result.IsFailure(out IError error) ``` -------------------------------- ### New IsFailure overload to get error and value Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/breaking-changes.md Retrieve the error details and any associated value from a result using this overload. ```csharp result.IsFailure(out IError error, out TValue value) ``` -------------------------------- ### New IsSuccess overload to get value and error Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/breaking-changes.md Retrieve the success value and any associated error from a result using this overload. ```csharp result.IsSuccess(out TValue value, out IError error) ``` -------------------------------- ### Get Value from Successful Result Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/getting-started.md Retrieve the value from a successful result using the `out` parameter of the `IsSuccess()` method. ```csharp if (result.IsSuccess(out var value)) { Console.WriteLine($"Value is {value}"); } ``` -------------------------------- ### Get string representation of a failed result in LightResults Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/performance.md Convert a failed result to its string representation using `ToString()`. This will typically indicate the failure state. ```csharp Result.Failure().ToString() ``` -------------------------------- ### Get string representation of a successful value result in LightResults Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/performance.md Convert a successful result that contains a value to its string representation using `ToString()`. This includes the value in the output. ```csharp Result.Success(value).ToString() ``` -------------------------------- ### Retrieve the first error from a failed result in LightResults Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/performance.md Access the `Error` property to get the first error message from a failed result. This provides direct access to the error details. ```csharp result.Error ``` -------------------------------- ### Get string representation of a failed result with an error message in LightResults Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/performance.md Convert a failed result that includes an error message to its string representation using `ToString()`. This provides the specific reason for failure. ```csharp Result.Failure(errorMessage).ToString() ``` -------------------------------- ### Get string representation of a failed value result with an error message in LightResults Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/performance.md Convert a failed result that was intended to hold a value but failed, and includes an error message, to its string representation using `ToString()`. This provides detailed failure information in a value context. ```csharp Result.Failure(errorMessage).ToString() ``` -------------------------------- ### Get string representation of a failed value result in LightResults Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/performance.md Convert a failed result that was intended to hold a value but failed, to its string representation using `ToString()`. This indicates a failure in a value-carrying context. ```csharp Result.Failure().ToString() ``` -------------------------------- ### Build and Test LightResults Library Source: https://github.com/jscarle/lightresults/blob/develop/AGENTS.md Commands to restore, build, and test the LightResults library using the .NET SDK. Specify a target framework like 'net10.0' for testing. ```bash # Restore and build dotnet build LightResults.sln # Run tests dotnet test tests/LightResults.Tests/LightResults.Tests.csproj -f net10.0 ``` -------------------------------- ### Usage Pattern Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Recommended patterns for using the LightResults library. ```APIDOC ## Usage Pattern 1. Create results using the static `Result` methods rather than constructors. 2. Check results with `IsSuccess()`/`IsFailure()` before accessing values or errors. 3. Use `HasError()` to branch on specific error types. 4. Custom errors can inherit from `Error` to represent domain-specific failures. 5. Convert failed results to another type with `AsFailure()` or `AsFailure()`. 6. Prefer returning `Result` or `Result` from methods instead of throwing exceptions. ``` -------------------------------- ### Create Errors with Messages and Metadata Source: https://github.com/jscarle/lightresults/blob/develop/README.md Demonstrates creating Error instances with various combinations of messages, metadata (tuples, dictionaries, KeyValuePairs, enumerables), and exceptions. ```csharp var emptyError = Error.Empty; var errorWithoutMessage = new Error(); var errorWithMessage = new Error("Something went wrong!"); ``` ```csharp var errorWithMetadataTuple = new Error("Something went wrong!", ("Key", "Value")); var metadata = new Dictionary { { "Key", "Value" } }; var errorWithMetadataDictionary = new Error("Something went wrong!", metadata); var errorWithMetadataKeyValuePair = new Error("Something went wrong!", new KeyValuePair("Key", "Value")); var errorWithMetadataEnumerable = new Error("Something went wrong!", new[] { new KeyValuePair("Key", "Value") }); var ex = new InvalidOperationException(); var errorWithException = new Error(ex); var errorWithMessageAndException = new Error("Something went wrong!", ex); ``` -------------------------------- ### New Error constructor with KeyValuePair metadata Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/breaking-changes.md Create an Error object with a string message and a single KeyValuePair for metadata. ```csharp Error(string message, KeyValuePair metadata) ``` -------------------------------- ### Use the Error Factory in a Method Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/getting-started.md Return results from your methods using the error factory for consistent and readable error handling. ```csharp public Result GetPerson(int id) { var person = _database.GetPerson(id); if (person is null) return AppError.NotFound(); return Result.Success(); } ``` -------------------------------- ### Create an Error Factory for Common Errors Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/getting-started.md Simplify error creation by defining static methods that return pre-configured failed results with specific error types. ```csharp public static class AppError { public static Result NotFound() { var notFoundError = new NotFoundError(); return Result.Failure(notFoundError); } public static Result HttpError(HttpStatusCode statusCode) { var httpError = new HttpError(statusCode); return Result.Failure(httpError); } } ``` -------------------------------- ### Create Successful Results Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/getting-started.md Use the `Success` method to create a successful result. Overloads allow for results with or without a value. ```csharp var successResult = Result.Success(); ``` ```csharp var successResultWithValue = Result.Success(349.4); ``` -------------------------------- ### Rename Result.Ok to Result.Success Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/breaking-changes.md Use Result.Success() for creating success results with a value. This replaces the older Result.Ok() method and allows omitting the type when known. ```csharp Result.Success() ``` -------------------------------- ### Create Success Results with LightResults Source: https://context7.com/jscarle/lightresults/llms.txt Use Result.Success() to create successful outcomes. Overloads allow for results with or without a value, including complex types. Implicit conversion from a value to a success result is also supported. ```csharp using LightResults; // Create a simple success result (no value) Result successResult = Result.Success(); // Create a success result with a value Result resultWithValue = Result.Success(349.4); // Create a success result with a complex type var user = new User { Id = 1, Name = "John Doe" }; Result userResult = Result.Success(user); // Implicit conversion from value to success result Result implicitResult = 42; // Equivalent to Result.Success(42) Console.WriteLine(successResult.IsSuccess()); // Output: True Console.WriteLine(resultWithValue.IsSuccess(out var value)); // Output: True Console.WriteLine($"Value: {value}"); // Output: Value: 349.4 ``` -------------------------------- ### Create a successful Result Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Use `Result.Success(TValue value)` to create a successful result that carries a specific value. ```csharp Result.Success(10) ``` -------------------------------- ### Create and Use Errors in C# Source: https://context7.com/jscarle/lightresults/llms.txt Demonstrates various ways to instantiate the `Error` class, including with messages, metadata (tuples, KeyValuePairs, dictionaries), and exceptions. Shows implicit conversion to `Result` types. ```csharp using LightResults; // Empty error var emptyError = new Error(); IError staticEmpty = Error.Empty; // Reusable empty instance // Error with message var simpleError = new Error("Something went wrong!"); // Error with message and tuple metadata var errorWithTuple = new Error("Validation failed", ("Field", "Email")); // Error with message and KeyValuePair metadata var errorWithKvp = new Error("Not found", new KeyValuePair("ResourceId", 42)); // Error with message and dictionary metadata var metadata = new Dictionary { { "StatusCode", 404 }, { "Path", "/api/users/123" } }; var errorWithDict = new Error("Resource not found", metadata); // Error with exception (message derived from exception) var exception = new InvalidOperationException("Database connection failed"); var errorFromException = new Error(exception); Console.WriteLine(errorFromException.Message); // Output: InvalidOperationException: Database connection failed // Error with custom message and exception var errorWithMsgAndEx = new Error("Failed to save data", exception); // Access exception from error if (errorFromException.Exception != null) { Console.WriteLine($"Exception type: {errorFromException.Exception.GetType().Name}"); } // Access metadata foreach (var kvp in errorWithDict.Metadata) { Console.WriteLine($"{kvp.Key}: {kvp.Value}"); } // Create failure result from error (implicit conversion) Result result = simpleError; // Implicit conversion to failure Result Result typedResult = simpleError; // Implicit conversion to failure Result ``` -------------------------------- ### Target Frameworks Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Supported .NET target frameworks for the LightResults library. ```APIDOC ## Target Frameworks This library targets `net8.0`, `net9.0`, and `net10.0` and is AOT-compatible. ``` -------------------------------- ### Namespaces Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Overview of the namespaces provided by the LightResults library. ```APIDOC # Namespaces - `LightResults` – contains `Result`, `Result`, `Error`, `IResult`, `IResult` and `IError`. - `LightResults.Common` – defines `IActionableResult` and `IActionableResult`; these static-abstract interfaces are available on the library's supported frameworks. ``` -------------------------------- ### Rename Result.Ok to Result.Success Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/breaking-changes.md Use Result.Success() for creating generic success results. This replaces the older Result.Ok() method. ```csharp Result.Success() ``` -------------------------------- ### Compare Errors for Equality Source: https://github.com/jscarle/lightresults/blob/develop/README.md Illustrates how `Error` instances with the same message and metadata are considered equal due to the implementation of `IEquatable`. ```csharp var error1 = new Error("Invalid", ("Code", 42)); var error2 = new Error("Invalid", ("Code", 42)); if (error1 == error2) { // Errors are equal } ``` -------------------------------- ### Create Error Objects Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/getting-started.md Instantiate `Error` objects with or without a message, and optionally include metadata or an exception. ```csharp var errorWithoutMessage = new Error(); ``` ```csharp var errorWithMessage = new Error("Something went wrong!"); ``` ```csharp var errorWithMetadataTuple = new Error("Something went wrong!", ("Key", "Value")); ``` ```csharp var metadata = new Dictionary { { "Key", "Value" } }; var errorWithMetadataDictionary = new Error("Something went wrong!", metadata); ``` ```csharp var errorWithMetadataKeyValuePair = new Error("Something went wrong!", new KeyValuePair("Key", "Value")); ``` ```csharp var errorWithMetadataEnumerable = new Error("Something went wrong!", new[] { new KeyValuePair("Key", "Value") }); ``` ```csharp var ex = new InvalidOperationException(); var errorWithException = new Error(ex); ``` ```csharp var errorWithMessageAndException = new Error("Something went wrong!", ex); ``` -------------------------------- ### New Error constructor with message and Exception Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/breaking-changes.md Create an Error object with a message and an associated Exception. ```csharp Error(string message, Exception exception) ``` -------------------------------- ### New Error constructor with Exception Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/breaking-changes.md Create an Error object directly from an Exception. ```csharp Error(Exception exception) ``` -------------------------------- ### Handle Exceptions by Returning a Result Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/getting-started.md Use try-catch blocks and return Result.Failure(exception) to convert exceptions into failed results, avoiding direct exception propagation. ```csharp public Result DoSomeWork() { try { // We must not throw an exception in this method! } catch(Exception ex) { return Result.Failure(ex); } return Result.Success(); } ``` -------------------------------- ### Create Failed Results Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/getting-started.md Use the `Failure` method to create a failed result. You can include a message, metadata, and an exception. ```csharp var failureResult = Result.Failure(); ``` ```csharp var failureResultWithMessage = Result.Failure("Operation failure!"); ``` ```csharp var failureResultWithMessageAndMetadata = Result.Failure("Operation failure!", ("UserId", userId)); ``` ```csharp var failureResultWithMessageAndException = Result.Failure("Operation failure!", ex); ``` -------------------------------- ### Create Failure Results with LightResults Source: https://context7.com/jscarle/lightresults/llms.txt Use Result.Failure() to create failed outcomes. Various overloads support adding error messages, metadata (as tuples, KeyValuePair, or Dictionary), and exceptions for detailed error reporting. ```csharp using LightResults; // Basic failure without details Result failureResult = Result.Failure(); // Failure with an error message Result failureWithMessage = Result.Failure("Operation failed!"); // Failure with message and metadata (tuple syntax) var userId = 123; Result failureWithMetadata = Result.Failure("User not found", ("UserId", userId)); // Failure with message and metadata (KeyValuePair) Result failureWithKvp = Result.Failure("Validation failed", new KeyValuePair("FieldName", "Email")); // Failure with message and metadata dictionary var metadata = new Dictionary { { "RequestId", Guid.NewGuid() }, { "Timestamp", DateTime.UtcNow } }; Result failureWithDict = Result.Failure("Server error", metadata); // Failure with exception try { throw new InvalidOperationException("Something went wrong"); } catch (Exception ex) { Result failureWithException = Result.Failure(ex); Result failureWithMsgAndEx = Result.Failure("Custom message", ex); } // Generic failure results (with type parameter) Result typedFailure = Result.Failure("Invalid input"); Result userFailure = Result.Failure("User not found"); Console.WriteLine(failureResult.IsFailure()); // Output: True ``` -------------------------------- ### New Error constructor with IEnumerable metadata Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/breaking-changes.md Create an Error object with a string message and an enumerable collection of KeyValuePairs for metadata. ```csharp Error(string message, IEnumerable> metadata) ``` -------------------------------- ### Add Failure result with KeyValuePair metadata Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/breaking-changes.md Create a failure result with an error message and a single KeyValuePair for metadata. ```csharp Result.Failure(string errorMessage, KeyValuePair metadata) ``` -------------------------------- ### Add generic Failure result with KeyValuePair metadata Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/breaking-changes.md Create a generic failure result with an error message and a single KeyValuePair for metadata. ```csharp Result.Failure(string errorMessage, KeyValuePair metadata) ``` -------------------------------- ### Rename Result.Fail to Result.Failure Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/breaking-changes.md Use Result.Failure() for creating failure results with a value. This replaces the older Result.Fail() method. ```csharp Result.Failure() ``` -------------------------------- ### IActionableResult Interface Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Defines methods for creating actionable results. ```APIDOC ## IActionableResult Interface - extends `IResult` - generic constraint: `where TResult : IResult` - `static abstract TResult Success()` - `static abstract TResult Failure()` - `static abstract TResult Failure(string errorMessage)` - `static abstract TResult Failure(string errorMessage, (string Key, object? Value) metadata)` - `static abstract TResult Failure(string errorMessage, KeyValuePair metadata)` - `static abstract TResult Failure(string errorMessage, IReadOnlyDictionary metadata)` - `static abstract TResult Failure(Exception? ex)` - `static abstract TResult Failure(string errorMessage, Exception? ex)` - `static abstract TResult Failure(IError error)` - `static abstract TResult Failure(IEnumerable errors)` - `static abstract TResult Failure(IReadOnlyList errors)` ``` -------------------------------- ### Check Result State with IsSuccess and IsFailure Source: https://context7.com/jscarle/lightresults/llms.txt Use IsSuccess() and IsFailure() to determine a result's state. Out parameters allow safely extracting the value or error details from the result object. ```csharp using LightResults; // Simple state checks Result result = Result.Success(42); if (result.IsSuccess()) { Console.WriteLine("Operation succeeded!"); } if (result.IsFailure()) { Console.WriteLine("Operation failed!"); } // Get value from success result if (result.IsSuccess(out var value)) { Console.WriteLine($"Value is: {value}"); // Output: Value is: 42 } // Get error from failure result Result failedResult = Result.Failure("Something went wrong"); if (failedResult.IsFailure(out var error)) { Console.WriteLine($"Error: {error.Message}"); // Output: Error: Something went wrong } // Get both value and error in one call Result priceResult = Result.Success(19.99m); if (priceResult.IsSuccess(out var price, out var err)) { Console.WriteLine($"Price: ${price}"); // Output: Price: $19.99 } else { Console.WriteLine($"Error: {err.Message}"); } // Alternative: IsFailure with both error and value if (priceResult.IsFailure(out var failError, out var failValue)) { Console.WriteLine($"Failed with: {failError.Message}"); } else { Console.WriteLine($"Success with value: {failValue}"); } ``` -------------------------------- ### Implicit conversion from TValue to success Result Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md A `TValue` can be implicitly converted to a successful `Result`. ```csharp Result result = 10; ``` -------------------------------- ### Chain Operations with Then Source: https://github.com/jscarle/lightresults/wiki/Labs Use the Then extension method to chain operations that return a Result. If the current Result is a success, the next function is executed. Otherwise, the current Result is returned. ```csharp public static Result Then(this Result result, Func next) { if (result.IsSuccess()) return next(); return result; } ``` ```csharp public static Result Then(this Result result, Func> next) { if (result.IsSuccess(out var value)) return next(value); return result.AsFailure(); } ``` ```csharp public static Result Then(this Result result, Func next) { if (result.IsSuccess(out var value)) return next(value); return result.AsFailure(); } ``` -------------------------------- ### Convert Exceptions to Results Source: https://context7.com/jscarle/lightresults/llms.txt Handle exceptions gracefully by converting them into `Result.Failure` objects. This allows for consistent error handling without losing exception details. ```csharp using LightResults; public class DataService { public Result ReadFile(string path) { try { var content = File.ReadAllText(path); return Result.Success(content); } catch (FileNotFoundException ex) { return Result.Failure("File not found", ex); } catch (UnauthorizedAccessException ex) { return Result.Failure("Access denied", ex); } catch (Exception ex) { return Result.Failure(ex); // Uses exception message automatically } } public Result SaveData(string data) { try { // Simulate database operation if (string.IsNullOrEmpty(data)) throw new ArgumentException("Data cannot be empty", nameof(data)); // Save operation... return Result.Success(); } catch (Exception ex) { return Result.Failure(ex); } } } // Usage var service = new DataService(); var readResult = service.ReadFile("/nonexistent/path.txt"); if (readResult.IsFailure(out var error)) { Console.WriteLine($"Error: {error.Message}"); // Access the original exception if needed if (error.Exception is FileNotFoundException fnfEx) { Console.WriteLine($"Missing file: {fnfEx.FileName}"); } // Or check via metadata if (error.Metadata.TryGetValue("Exception", out var exObj) && exObj is Exception ex) { Console.WriteLine($"Exception type: {ex.GetType().Name}"); } } ``` -------------------------------- ### Resolve Results with Actions Source: https://github.com/jscarle/lightresults/wiki/Labs Use the Resolve extension method to execute specific actions based on whether the Result is a success or a failure. This method takes success and failure callbacks. ```csharp public static void Resolve(this Result result, Action onSuccess, Action onFailure) { if (result.IsFailure(out var error)) { onFailure(error); return; } onSuccess(); } ``` ```csharp public static void Resolve(this Result result, Action onSuccess, Action onFailure) { if (result.IsSuccess(out var value, out var error)) { onSuccess(value); return; } onFailure(error); } ``` -------------------------------- ### Create a failed Result with metadata Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Use `Result.Failure` overloads to include key-value pair metadata with the error message. ```csharp Result.Failure("An error occurred", ("Key", "Value")) ``` ```csharp Result.Failure("An error occurred", new KeyValuePair("Key", "Value")) ``` -------------------------------- ### Create a Result with a Custom Error Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/getting-started.md Use Result.Failure() to create a failed result with your custom error instance. ```csharp var notFoundError = new NotFoundError(); var notFoundResult = Result.Failure(notFoundError); ``` -------------------------------- ### Return Success Value Result - LightResults Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/performance.md Use `Result.Success(value)` to return a successful result with an associated value. This method is highly performant. ```csharp Result.Success(value) ``` -------------------------------- ### Create a failed Result from an Exception Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Use `Result.Failure(Exception? ex)` to create a failed result of a specific type, deriving the message from an exception. ```csharp Result.Failure(new InvalidOperationException("Cannot get value")) ``` -------------------------------- ### Create a failed Result with a message and Exception Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Use `Result.Failure(string message, Exception? ex)` to create a failed result with a custom message and an associated exception. ```csharp Result.Failure("User not found", new Exception("Database error")) ``` -------------------------------- ### Define Custom Error Class Source: https://github.com/jscarle/lightresults/blob/develop/README.md Illustrates creating a custom error type `NotFoundError` by inheriting from `Error` and setting a default message. This is the recommended way to represent specific error conditions. ```csharp public sealed class NotFoundError : Error { public NotFoundError() : base("The resource cannot be found.") { } } var notFoundError = new NotFoundError(); var notFoundResult = Result.Failure(notFoundError); ``` -------------------------------- ### Create a failed Result with a message Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Use `Result.Failure(string message)` to create a failed result of a specific type without a value. ```csharp Result.Failure("Value not available") ``` -------------------------------- ### Create Custom Errors with Error Factory Source: https://context7.com/jscarle/lightresults/llms.txt Define custom error types and use a static factory class to create domain-specific failure results. This promotes a consistent API for error generation. ```csharp using LightResults; using System.Net; // Custom error types public sealed class NotFoundError : Error { public NotFoundError(string message) : base(message) { } } public sealed class UnauthorizedError : Error { public UnauthorizedError() : base("Access denied. Authentication required.") { } } // Error factory for centralized error creation public static class AppError { public static Result NotFound(string resource = "Resource") { return Result.Failure(new NotFoundError($"{resource} was not found.")); } public static Result NotFound(string resource = "Resource") { return Result.Failure(new NotFoundError($"{resource} was not found.")); } public static Result Unauthorized() { return Result.Failure(new UnauthorizedError()); } public static Result Unauthorized() { return Result.Failure(new UnauthorizedError()); } public static Result ValidationFailed(string message, string fieldName) { return Result.Failure(message, ("FieldName", fieldName)); } } // Service using the error factory public class UserService { private readonly Dictionary _users = new(); public Result GetUser(int id) { if (!_users.TryGetValue(id, out var user)) return AppError.NotFound("User"); return Result.Success(user); } public Result UpdateEmail(int userId, string email) { if (string.IsNullOrWhiteSpace(email)) return AppError.ValidationFailed("Email cannot be empty", "Email"); if (!_users.ContainsKey(userId)) return AppError.NotFound("User"); _users[userId].Email = email; return Result.Success(); } } // Usage var service = new UserService(); var result = service.GetUser(999); if (result.IsFailure(out var error)) { Console.WriteLine(error.Message); // Output: User was not found. } public class User { public int Id { get; set; } public string Name { get; set; } = ""; public string Email { get; set; } = ""; } ``` -------------------------------- ### Add Failure result with message and Exception Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/breaking-changes.md Create a failure result with a custom error message and an associated Exception. ```csharp Result.Failure(string errorMessage, Exception ex) ``` -------------------------------- ### Retrieve error and value from Result Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Use `IsSuccess(out TValue value, out IError error)` to retrieve both the value and the first error if the result is successful. ```csharp result.IsSuccess(out var value, out var error) ``` -------------------------------- ### Create a failed Result from an Exception Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Use `Result.Failure(Exception? ex)` to create a failed result where the error message is derived from the exception. The exception is stored under the key "Exception". ```csharp Result.Failure(new Exception("Something went wrong")) ``` -------------------------------- ### Check Result State Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/getting-started.md Use `IsSuccess()` and `IsFailure()` to determine the state of a result. `IsFailure()` can optionally output the error details. ```csharp if (result.IsSuccess()) { // The result is successful. } ``` ```csharp if (result.IsFailure(out var error)) { // The result is failure. if (error.Message.Length > 0) Console.WriteLine(error.Message); else Console.WriteLine("An unknown error occurred!"); } ``` -------------------------------- ### Add generic Failure result with message and Exception Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/breaking-changes.md Create a generic failure result with a custom error message and an associated Exception. ```csharp Result.Failure(string errorMessage, Exception ex) ``` -------------------------------- ### Define a Custom NotFoundError Class Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/getting-started.md Inherit from the base Error class to create specific error types. Pass the error message to the base constructor. ```csharp public sealed class NotFoundError : Error { public NotFoundError() : base("The resource cannot be found.") { } } ``` -------------------------------- ### Define an HttpError Class with Metadata Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/getting-started.md Create custom errors that include additional metadata, such as an HttpStatusCode, by passing tuples to the base constructor. ```csharp public sealed class HttpError : Error { public HttpError(HttpStatusCode statusCode) : base("An HTTP error occurred.", ("StatusCode", statusCode)) { } } ``` -------------------------------- ### Create a failed Result from multiple Errors Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Use `Result.Failure(IEnumerable errors)` or `Result.Failure(IReadOnlyList errors)` to create a failed result containing a collection of errors. ```csharp Result.Failure(new List { new Error("Error 1"), new Error("Error 2") }) ``` ```csharp Result.Failure(new List { new Error("Error 1"), new Error("Error 2") }.AsReadOnly()) ``` -------------------------------- ### IActionableResult Interface Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Defines methods for creating actionable results with a value. ```APIDOC ## IActionableResult Interface - extends `IResult` - generic constraint: `where TResult : IResult` - `static abstract TResult Success(TValue value)` - `static abstract TResult Failure()` - `static abstract TResult Failure(string errorMessage)` - `static abstract TResult Failure(string errorMessage, (string Key, object? Value) metadata)` - `static abstract TResult Failure(string errorMessage, KeyValuePair metadata)` - `static abstract TResult Failure(string errorMessage, IReadOnlyDictionary metadata)` - `static abstract TResult Failure(Exception? ex)` - `static abstract TResult Failure(string errorMessage, Exception? ex)` - `static abstract TResult Failure(IError error)` - `static abstract TResult Failure(IEnumerable errors)` - `static abstract TResult Failure(IReadOnlyList errors)` ``` -------------------------------- ### Add Failure result with Exception Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/breaking-changes.md Create a failure result directly from an Exception object. ```csharp Result.Failure(Exception ex) ``` -------------------------------- ### Return Failure Result with Error Message - LightResults Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/performance.md Use `Result.Failure(errorMessage)` to return a failed result with a specific error message. This is efficient for conveying failure reasons. ```csharp Result.Failure(errorMessage) ``` -------------------------------- ### Rename Result.Fail to Result.Failure Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/breaking-changes.md Use Result.Failure() for creating generic failure results. This replaces the older Result.Fail() method. ```csharp Result.Failure() ``` -------------------------------- ### Convert Failed Results with AsFailure Source: https://context7.com/jscarle/lightresults/llms.txt Use AsFailure() and AsFailure() to convert a failed result to a different result type while preserving the error information. This is useful for propagating errors through different layers of an application. ```csharp using LightResults; public class OrderService { private readonly UserService _userService; private readonly InventoryService _inventoryService; public Result CreateOrder(int userId, int productId) { // Get user - if failed, convert to Order result type var userResult = _userService.GetUser(userId); if (userResult.IsFailure()) { return userResult.AsFailure(); // Preserves original error } // Check inventory var stockResult = _inventoryService.CheckStock(productId); if (stockResult.IsFailure()) { return stockResult.AsFailure(); } // Create order with the retrieved data if (userResult.IsSuccess(out var user) && stockResult.IsSuccess(out var stock)) { var order = new Order { UserId = user.Id, ProductId = productId, Quantity = 1 }; return Result.Success(order); } return Result.Failure("Unexpected error"); } } // Converting between result types Result intResult = Result.Failure("Invalid number"); // Convert to different generic type Result stringResult = intResult.AsFailure(); // Convert to non-generic Result Result plainResult = intResult.AsFailure(); // All preserve the original error Console.WriteLine(stringResult.IsFailure(out var err1)); // True Console.WriteLine(err1.Message); // "Invalid number" Console.WriteLine(plainResult.IsFailure(out var err2)); // True Console.WriteLine(err2.Message); // "Invalid number" public class Order { public int UserId; public int ProductId; public int Quantity; } public class UserService { public Result GetUser(int id) => Result.Failure("Not found"); } public class InventoryService { public Result CheckStock(int id) => Result.Success(10); } public class User { public int Id; } ``` -------------------------------- ### IError Interface Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Defines the contract for an error object. ```APIDOC ## IError Interface - `string Message { get; }` - `Exception? Exception { get; }` - `IReadOnlyDictionary Metadata { get; }` ``` -------------------------------- ### Ensure a Result is a failure Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Use `AsFailure()` to ensure the result is a failure, preserving existing errors. This is useful for chaining operations. ```csharp result.AsFailure() ``` -------------------------------- ### Check if a result is failed in LightResults Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/performance.md Use the `IsFailure()` method to determine if a result indicates a failure. This is a direct and efficient check. ```csharp result.IsFailure() ``` -------------------------------- ### Add generic Failure result with Exception Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/breaking-changes.md Create a generic failure result directly from an Exception object. ```csharp Result.Failure(Exception ex) ``` -------------------------------- ### Return Failure Value Result - LightResults Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/performance.md Use `Result.Failure()` to return a failed result with a value type but no specific error message. This is a very fast operation. ```csharp Result.Failure() ``` -------------------------------- ### Check if Result is Successful - LightResults Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/performance.md Use the `result.IsSuccess()` method to efficiently determine if a result indicates success. This is a very fast check. ```csharp result.IsSuccess() ``` -------------------------------- ### Create a failed Result from an IError Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Use `Result.Failure(IError error)` to create a failed result initialized with a specific `IError` instance. ```csharp Result.Failure(new Error("Invalid input")) ``` -------------------------------- ### Create a failed Result with a message Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Use `Result.Failure(string message)` to create a failed result with a specific error message. ```csharp Result.Failure("An error occurred") ``` -------------------------------- ### Convert result to a failure result of another type Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/breaking-changes.md Use result.AsFailure() or result.AsFailure() to convert an existing result into a failure result of a different type. ```csharp result.AsFailure() ``` ```csharp result.AsFailure() ``` -------------------------------- ### Rename generic Result.Fail to Result.Failure Source: https://github.com/jscarle/lightresults/blob/develop/README.md Use Result.Failure() for creating generic failure results with a specified type. This replaces the older Result.Fail() method. ```csharp Result.Failure( ``` -------------------------------- ### Chain Asynchronous Operations with ThenAsync Source: https://github.com/jscarle/lightresults/wiki/Labs Use ThenAsync to chain asynchronous operations. If the current Result is a success, the next asynchronous function is executed. Otherwise, the current Result is returned. ```csharp public static Task ThenAsync(this Result result, Func> next) { if (result.IsSuccess()) return next(); return Task.FromResult(result); } ``` ```csharp public static Task> ThenAsync(this Result result, Func>> next) { if (result.IsSuccess(out var value)) return next(value); return Task.FromResult(result.AsFailure()); } ``` ```csharp public static Task ThenAsync(this Result result, Func> next) { if (result.IsSuccess(out var value)) return next(value); return Task.FromResult(result.AsFailure()); } ``` -------------------------------- ### Error Equality Comparison Source: https://context7.com/jscarle/lightresults/llms.txt The Error class implements IEquatable, allowing errors to be compared for equality based on their message and metadata. Errors with identical messages and metadata are considered equal. This functionality is useful for checking if a specific error has occurred within a result. ```csharp using LightResults; // Errors with same message are equal var error1 = new Error("Connection failed"); var error2 = new Error("Connection failed"); Console.WriteLine(error1 == error2); // Output: True Console.WriteLine(error1.Equals(error2)); // Output: True // Errors with same message and metadata are equal var errorWithMeta1 = new Error("Validation failed", ("Field", "Email")); var errorWithMeta2 = new Error("Validation failed", ("Field", "Email")); Console.WriteLine(errorWithMeta1 == errorWithMeta2); // Output: True // Different metadata means not equal var errorWithMeta3 = new Error("Validation failed", ("Field", "Phone")); Console.WriteLine(errorWithMeta1 == errorWithMeta3); // Output: False // Different messages means not equal var error3 = new Error("Different message"); Console.WriteLine(error1 == error3); // Output: False // Works with collections var errorSet = new HashSet { new Error("Duplicate check", ("Code", 1)), new Error("Duplicate check", ("Code", 1)), // Won't be added (duplicate) new Error("Duplicate check", ("Code", 2)) // Will be added (different metadata) }; Console.WriteLine($"Unique errors: {errorSet.Count}"); // Output: Unique errors: 2 // Useful for checking if specific error occurred var knownError = new Error("Service unavailable"); var result = Result.Failure(new Error("Service unavailable")); if (result.IsFailure(out var resultError) && resultError is Error e && e == knownError) { Console.WriteLine("Known error occurred - retry later"); } ``` -------------------------------- ### Resolve Asynchronous Results with Actions Source: https://github.com/jscarle/lightresults/wiki/Labs Use ResolveAsync to handle asynchronous Results. It takes asynchronous callbacks for success and failure scenarios. ```csharp public static Task ResolveAsync(this Result result, Func onSuccess, Func onFailure) { if (result.IsFailure(out var error)) return onFailure(error); return onSuccess(); } ``` ```csharp public static Task ResolveAsync(this Result result, Func onSuccess, Func onFailure) { if (result.IsSuccess(out var value, out var error)) return onSuccess(value); return onFailure(error); } ``` -------------------------------- ### Return Failure Value Result with Error Message - LightResults Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/performance.md Use `Result.Failure(errorMessage)` to return a failed result with both a value type and an error message. This method is optimized for performance. ```csharp Result.Failure(errorMessage) ``` -------------------------------- ### Result Type Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Documentation for the `Result` struct, which represents a result carrying a value on success. ```APIDOC ## Result (readonly struct) ### Description Represents a result carrying a value on success. Constructors are internal. Create instances using the static `Result` methods or via the implicit conversions from `TValue` and `Error`. ### Instance Members - `bool IsSuccess()` - `bool IsSuccess(out TValue value)` - `bool IsSuccess(out TValue value, out IError error)` - `bool IsFailure()` - `bool IsFailure(out IError error)` - `bool IsFailure(out IError error, out TValue value)` - `bool HasError()` / `bool HasError(out TError error)` – `TError : IError` - `Result AsFailure()` – ensure a failed result preserving existing errors. - `Result AsFailure()` - `IReadOnlyCollection Errors` ### Conversions - Implicit conversions: `TValue` → success result, `Error` → failure result. ### Equality - Implements `IEquatable>` with `Equals(in Result)` and `Equals(object?)`. - Provides `GetHashCode()`. - Supports `==`/`!=` operators. - Overrides `ToString()`. ### Interfaces - Implements `IResult` and `IActionableResult>`. ``` -------------------------------- ### IResult Interface Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Defines the contract for a result object, indicating success or failure. ```APIDOC ## IResult Interface - `IReadOnlyCollection Errors` - `bool IsSuccess()` - `bool IsFailure()` - `bool IsFailure(out IError error)` - `bool HasError()` – `TError : IError` - `bool HasError(out TError error)` – `TError : IError` ``` -------------------------------- ### Implicit conversion from Error to failure Result Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md An `Error` instance can be implicitly converted to a failed `Result`. ```csharp Result result = new Error("Failed"); ``` -------------------------------- ### Result Type Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Documentation for the `Result` struct, which represents a success or failure without a value. ```APIDOC ## Result (readonly struct) ### Description Represents a success or failure without a value. Constructors are private or internal – no public constructors exist. Use the static factory methods below to create instances. ### Static Factory Methods #### Creating Success Results - `Result.Success()` #### Creating Failure Results - `Result.Failure()` – failure with an empty error. - `Result.Failure(string message)` - `Result.Failure(string message, (string Key, object? Value) metadata)` - `Result.Failure(string message, KeyValuePair metadata)` - `Result.Failure(string message, IReadOnlyDictionary metadata)` - `Result.Failure(Exception? ex)` – derives the message from the exception and stores the exception under "Exception" in the resulting error. - `Result.Failure(string message, Exception? ex)` - `Result.Failure(IError error)` - `Result.Failure(IEnumerable errors)` - `Result.Failure(IReadOnlyList errors)` #### Creating Generic Success Results (`Result`) - `Result.Success(TValue value)` #### Creating Generic Failure Results (`Result`) - `Result.Failure()` - `Result.Failure(string message)` - `Result.Failure(string message, (string Key, object? Value) metadata)` - `Result.Failure(string message, KeyValuePair metadata)` - `Result.Failure(string message, IReadOnlyDictionary metadata)` - `Result.Failure(Exception? ex)` – derives the message from the exception and stores the exception under "Exception" in the resulting error. - `Result.Failure(string message, Exception? ex)` - `Result.Failure(IError error)` - `Result.Failure(IEnumerable errors)` - `Result.Failure(IReadOnlyList errors)` ### Instance Members - `bool IsSuccess()` - `bool IsFailure()` - `bool IsFailure(out IError error)` – retrieves the first error. - `bool HasError()` / `bool HasError(out TError error)` – `TError : IError` - `Result AsFailure()` – ensure a failed result preserving existing errors. - `Result AsFailure()` – convert to a different failure type. - `IReadOnlyCollection Errors` ### Conversions - Implicit conversion from `Error` to `Result`. ### Equality - Implements `IEquatable` with `Equals(in Result)` and `Equals(object?)`. - Provides `GetHashCode()`. - Supports `==`/`!=` operators. - Overrides `ToString()`. ### Interfaces - Implements `IResult` and `IActionableResult`. ``` -------------------------------- ### Check for a specific error type and retrieve it Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Use `HasError(out TError error)` to check for an error of a specific type and retrieve it if present. ```csharp result.HasError(out var ex) ``` -------------------------------- ### Generic Error Factory with Static Abstract Members Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/getting-started.md Enhance the error factory using static abstract members in interfaces (available in .NET 7.0+). This allows creating results of a generic type TResult. ```csharp public static class AppError { public static Result NotFound() { var notFoundError = new NotFoundError(); return Result.Failure(notFoundError); } public static TResult NotFound() where TResult : IResult { var notFoundError = new NotFoundError(); return TResult.Failure(notFoundError); } } ``` -------------------------------- ### Access Exception from Error Object Source: https://github.com/jscarle/lightresults/blob/develop/README.md Shows how to retrieve the underlying exception from an Error object using the `Exception` property. This works for both `Error` and `IError` types. ```csharp var ex = new InvalidOperationException("Something went wrong!"); var error = new Error(ex); if (error.Exception != null) { Console.WriteLine($"Exception: {error.Exception.Message}"); } // Also works with IError interface IError interfaceError = error; if (interfaceError.Exception != null) { Console.WriteLine($"Exception: {interfaceError.Exception.Message}"); } ``` -------------------------------- ### Convert Failed Results Source: https://github.com/jscarle/lightresults/blob/develop/docfx/docs/getting-started.md Use `AsFailure` to convert a failed result to another result type, including non-generic or generic types. ```csharp var result = Result.Failure("Invalid input"); var typed = result.AsFailure(); var backToNonGeneric = typed.AsFailure(); ``` -------------------------------- ### Convert a Result to a different failure type Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Use `AsFailure()` to convert a `Result` or `Result` to a failure result of a different type, preserving errors. ```csharp result.AsFailure() ``` -------------------------------- ### IResult Interface Source: https://github.com/jscarle/lightresults/blob/develop/EXPLAIN.md Extends IResult to include a value of a specific type. ```APIDOC ## IResult Interface - `bool IsSuccess(out TValue value)` - `bool IsSuccess(out TValue value, out IError error)` - `bool IsFailure(out IError error, out TValue value)` ``` -------------------------------- ### Check Result for Specific Custom Error Type Source: https://github.com/jscarle/lightresults/blob/develop/README.md Demonstrates how to check if a `Result` contains a specific custom error type, such as `NotFoundError`, using pattern matching or the `HasError` method. ```csharp if (result.IsFailure(out var error) && error is NotFoundError) { // Looks like the resource was not found, we better do something about that! } ``` ```csharp if (result.IsFailure() && result.HasError()) { // At least one of the errors was a NotFoundError. } ```