diff --git a/Incendium.Result/Error.cs b/Incendium.Result/Error.cs index 0bdae2c..f4f5911 100644 --- a/Incendium.Result/Error.cs +++ b/Incendium.Result/Error.cs @@ -3,12 +3,13 @@ namespace Incendium { /// - /// Represents error struct that contains code, message and exception + /// Represents error type that contains code, message, exception and inner error /// /// Error code /// Error message /// Inner exception - public readonly struct Error(int code, string? message, Exception? exception) + /// Inner error + public class Error(int code, string? message, Exception? exception, Error? innerError) { /// /// Gets error code @@ -22,51 +23,74 @@ public readonly struct Error(int code, string? message, Exception? exception) /// Gets inner exception /// public Exception? Exception { get; init; } = exception; + /// + /// Gets inner error + /// + public Error? InnerError { get; init; } = innerError; + + /// + /// Initialize a new instance of the error + /// + public Error() + : this(0, message: null, exception: null, innerError: null) + { + } /// - /// Initialize a new instance of the error struct with a specified error code + /// Initialize a new instance of the error with a specified error code /// /// Error code public Error(int code) - : this(code, message: null, exception: null) + : this(code, message: null, exception: null, innerError: null) { } /// - /// Initialize a new instance of the error struct with a specified error message + /// Initialize a new instance of the error with a specified error message /// /// Error message public Error(string message) - : this(code: 0, message: message, exception: null) + : this(code: 0, message: message, exception: null, innerError: null) { } /// - /// Initialize a new instance of the error struct with a specified inner exception + /// Initialize a new instance of the error with a specified inner exception /// /// Inner exception public Error(Exception exception) - : this(code: 0, message: null, exception: exception) + : this(code: 0, message: null, exception: exception, innerError: null) { } /// - /// Initialize a new instance of the error struct with a specified error code and message + /// Initialize a new instance of the error with a specified error code and message /// /// Error code /// Error message public Error(int code, string message) - : this(code, message, exception: null) + : this(code, message, exception: null, innerError: null) { } /// - /// Initialize a new instance of the error struct with a specified error message and inner exception + /// Initialize a new instance of the error with a specified error message and inner exception /// /// Error message /// Inner exception public Error(string message, Exception exception) - : this(code: 0, message, exception: exception) + : this(code: 0, message, exception: exception, innerError: null) + { + } + + /// + /// Initialize a new instance of the error with a specified error code, message and inner error + /// + /// Error code + /// Error message + /// Inner error + public Error(int code, string message, Error? error) + : this(code, message, exception: null, innerError: error) { } } diff --git a/Incendium.Result/Extensions/ErrorExtensions.cs b/Incendium.Result/Extensions/ErrorExtensions.cs deleted file mode 100644 index da576ae..0000000 --- a/Incendium.Result/Extensions/ErrorExtensions.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; - -namespace Incendium.Extensions -{ - public static class ErrorExtensions - { - /// - /// Gets error code - /// - /// Nullable error - /// Error code - public static int Code(this Error? error) => error!.Value.Code; - /// - /// Gets error message - /// - /// Nullable error - /// Error message - public static string Message(this Error? error) => error!.Value.Message; - /// - /// Gets inner exception - /// - /// Nullable error - /// Inner exception - public static Exception? Exception(this Error? error) => error!.Value.Exception; - } -} diff --git a/Incendium.Result/Incendium.Result.csproj b/Incendium.Result/Incendium.Result.csproj index db3c1c9..97bc7f9 100644 --- a/Incendium.Result/Incendium.Result.csproj +++ b/Incendium.Result/Incendium.Result.csproj @@ -19,7 +19,7 @@ Incendium.Result mativ Provides a Result<T> type that allows a method to return both a value and an error in Rust style without exceptions - 1.0.2 + 1.0.3 Copyright © Igor Matsak diff --git a/Incendium.Result/NullableResult.cs b/Incendium.Result/NullableResult.cs index 530a632..c73f978 100644 --- a/Incendium.Result/NullableResult.cs +++ b/Incendium.Result/NullableResult.cs @@ -31,16 +31,6 @@ public NullableResult(T? value) /// /// Error public NullableResult(Error error) - { - Error = error; - } - - /// - /// Initialize a result instance from the non-null error value with nullable type - /// - /// Non-null error value with nullable type - /// - public NullableResult(Error? error) { Error = error ?? throw new ArgumentNullException(nameof(error)); } @@ -55,13 +45,6 @@ public NullableResult(Error? error) /// /// Error public static implicit operator NullableResult(Error error) => new(error); - /// - /// Initialize a result instance from the non-null error value with nullable type - /// - /// Non-null error value with nullable type - /// - public static implicit operator NullableResult(Error? error) => new(error); - /// /// Deconstruct struct to success value and error value /// diff --git a/Incendium.Result/README.md b/Incendium.Result/README.md index d0ee6fd..d9c896b 100644 --- a/Incendium.Result/README.md +++ b/Incendium.Result/README.md @@ -43,8 +43,8 @@ if (error != null) { log.LogError( error.Exception(), "Error with code {@code} and message {@message}", - error.Code(), - error.Message()); + error.Code, + error.Message); } ``` @@ -53,12 +53,15 @@ The `Result` instance can be created only from non-null value or from non-nul ```cs public Result GetFooAsync() { return new Foo(); // correct - return new Error(); // correct - return (Foo)null; // incorrect, CS8600 warning, throws ArgumentNullException - return (Foo)null!; // incorrect, throws ArgumentNullException - return (Foo?)null; // incorrect, CS8604 warning, throws ArgumentNullException - return (Foo?)null!; // incorrect, throws ArgumentNullException - return (Error?)null; // incorrect, throws ArgumentNullException + // return new Error(); // correct + // return (Foo)null; // incorrect, CS8600 and CS8625 warnings, throws ArgumentNullException + // return (Foo)null!; // incorrect, throws ArgumentNullException + // return (Foo?)null; // incorrect, CS8625 warning, throws ArgumentNullException + // return (Foo?)null!; // incorrect, throws ArgumentNullException + // return (Error)null; // incorrect, CS8600 and CS8625 warnings, throws ArgumentNullException + // return (Error)null!; // incorrect, throws ArgumentNullException + // return (Error?)null; // incorrect, CS8625 warning, throws ArgumentNullException + // return (Error?)null!; // incorrect, throws ArgumentNullException } ``` @@ -67,12 +70,15 @@ public Result GetFooAsync() { If the successful return value can be null, you must use the `NullableResult` type: ```cs -public async NullableResult GetFooAsync() { +public NullableResult GetFooAsync() { return new Foo(); // correct - return new Error(); // correct - return (Foo?)null; // correct - return (Foo)null; // correct with CS8600 warning - return (Foo)null!; // correct - return (Error?)null; // incorrect, throws ArgumentNullException + // return new Error(); // correct + // return (Foo?)null; // correct + // return (Foo)null; // correct with CS8600 warning + // return (Foo)null!; // correct + // return (Error)null; // incorrect, CS8600 and CS8625 warnings, throws ArgumentNullException + // return (Error)null!; // incorrect, throws ArgumentNullException + // return (Error?)null; // incorrect, CS8625 warning, throws ArgumentNullException + // return (Error?)null!; // incorrect, throws ArgumentNullException } ``` diff --git a/Incendium.Result/Result.cs b/Incendium.Result/Result.cs index 93830d3..69ba450 100644 --- a/Incendium.Result/Result.cs +++ b/Incendium.Result/Result.cs @@ -35,17 +35,6 @@ public Result(T value) /// /// Error public Result(Error error) - { - Value = default!; - Error = error; - } - - /// - /// Initialize a result instance from the non-null error value with nullable type - /// - /// Non-null error value with nullable type - /// - public Result(Error? error) { Value = default!; Error = error ?? throw new ArgumentNullException(nameof(error)); @@ -62,13 +51,6 @@ public Result(Error? error) /// /// Error public static implicit operator Result(Error error) => new(error); - /// - /// Initialize a result instance from the non-null error value with nullable type - /// - /// Non-null error value with nullable type - /// - public static implicit operator Result(Error? error) => new(error); - /// /// Deconstruct struct to success value and error value /// diff --git a/Incendium.Tests/Result/ResultsTests.cs b/Incendium.Tests/Result/ResultsTests.cs index 6918993..8cac3cf 100644 --- a/Incendium.Tests/Result/ResultsTests.cs +++ b/Incendium.Tests/Result/ResultsTests.cs @@ -1,5 +1,3 @@ -using Incendium.Extensions; - namespace Incendium.Result { public class ResultsTests @@ -27,12 +25,12 @@ public void Test_Result_FailCreateFromNullErrorValue() // asserts Assert.Throws(() => { - var result = new Result((Error?)null); + var result = new Result((Error)null!); }); Assert.Throws(() => { - Result result = (Error?)null; + Result result = (Error)null!; }); } @@ -58,10 +56,8 @@ public void Test_Result_DeconstructWhenError() // asserts Assert.Null(result); Assert.NotNull(error); - Assert.Equal(100, error.Value.Code); - Assert.Equal("Error", error.Value.Message); - Assert.Equal(100, error.Code()); - Assert.Equal("Error", error.Message()); + Assert.Equal(100, error.Code); + Assert.Equal("Error", error.Message); } [Fact] @@ -84,12 +80,12 @@ public void Test_NullableResult_FailCreateFromNullErrorValue() // asserts Assert.Throws(() => { - var result = new NullableResult((Error?)null); + var result = new NullableResult((Error)null!); }); Assert.Throws(() => { - NullableResult result = (Error?)null; + NullableResult result = (Error)null!; }); } @@ -115,10 +111,8 @@ public void Test_NullableResult_DeconstructWhenError() // asserts Assert.Null(result); Assert.NotNull(error); - Assert.Equal(100, error.Value.Code); - Assert.Equal("Error", error.Value.Message); - Assert.Equal(100, error.Code()); - Assert.Equal("Error", error.Message()); + Assert.Equal(100, error.Code); + Assert.Equal("Error", error.Message); } private static Result GetResult(bool withError)