diff --git a/docs/features-results.md b/docs/features-results.md index 642cfc1..88d194c 100644 --- a/docs/features-results.md +++ b/docs/features-results.md @@ -1011,8 +1011,7 @@ public async Task> ProcessOrderAsync(Order order) .FindOneResultAsync(order.ProductId); if (inventoryResult.IsFailure) - return Result.Failure() - .WithErrors(inventoryResult.Errors); + return inventoryResult.For(); // convert to Order result // Insert order var orderResult = await _orderRepository diff --git a/src/Common.Results/Result{T}.cs b/src/Common.Results/Result{T}.cs index 2c1af33..40ff2ac 100644 --- a/src/Common.Results/Result{T}.cs +++ b/src/Common.Results/Result{T}.cs @@ -258,6 +258,32 @@ public static implicit operator Result(Result result) => () => Success().WithMessages(result.Messages).WithErrors(result.Errors), _ => Failure().WithMessages(result.Messages).WithErrors(result.Errors)); + // /// + // /// Implicitly converts a Result{T} to a Result{TOutput}. + // /// + // /// The target type of the conversion. + // /// The Result{T} to convert. + // /// A new Result{TOutput} with the same success state, messages, and errors. + // /// + // /// + // /// var intResult = Result{int}.Failure() + // /// .WithMessage("Processing failed") + // /// .WithError(new ValidationError("Invalid value")); + // /// + // /// Result{string} strResult = intResult; // Implicit conversion + // /// + // /// + // public static implicit operator Result(Result result) + // { + // return result.Match( + // _ => Result.Success() + // .WithMessages(result.Messages) + // .WithErrors(result.Errors), + // _ => Result.Failure() + // .WithMessages(result.Messages) + // .WithErrors(result.Errors)); + // } + /// /// Creates a successful Result{T} with a specified value. /// diff --git a/tests/Common.UnitTests/Results/Result{T}Tests.cs b/tests/Common.UnitTests/Results/Result{T}Tests.cs index 78889bb..4e9899e 100644 --- a/tests/Common.UnitTests/Results/Result{T}Tests.cs +++ b/tests/Common.UnitTests/Results/Result{T}Tests.cs @@ -87,6 +87,19 @@ public void Failure_WithVariousOverloads_CreatesFailureResults() Should.Throw(() => result7.Value); } + public Result For_ConversionBetweenTypes1() + { + // Arrange + var value = this.faker.Random.Int(1, 100); + var message = this.faker.Lorem.Sentence(); + var error = new Error("Test error"); + + var successResult = Result.Success(value).WithMessage(message); + var failureResult = Result.Failure().WithMessage(message).WithError(error); + + return failureResult.For(); //explicit conversion + } + [Fact] public void For_ConversionBetweenTypes_MaintainsStateAndMessages() { @@ -916,4 +929,106 @@ public interface IDatabase Task PersonExistsAsync(EmailAddressStub email, CancellationToken ct); } + + [Fact] + public void ImplicitConversion_ValueToResult_WorksCorrectly() + { + // Arrange + var value = this.faker.Random.Int(1, 100); + + // Act + Result result = value; + + // Assert + result.ShouldBeSuccess(); + result.ShouldBeValue(value); + } + + [Fact] + public void ImplicitConversion_TaskToResult_WorksCorrectly() + { + // Arrange + var value = this.faker.Random.Int(1, 100); + var task = Task.FromResult(value); + + // Act + Result result = task; + + // Assert + result.ShouldBeSuccess(); + result.ShouldBeValue(value); + } + + [Fact] + public void ImplicitConversion_ResultToBool_WorksCorrectly() + { + // Arrange + var successResult = Result.Success(42); + var failureResult = Result.Failure(); + + // Act + bool successBool = successResult; + bool failureBool = failureResult; + + // Assert + successBool.ShouldBeTrue(); + failureBool.ShouldBeFalse(); + } + + [Fact] + public void ImplicitConversion_ResultToNonGenericResult_WorksCorrectly() + { + // Arrange + var successResult = Result.Success(42); + var failureResult = Result.Failure(); + + // Act + Result nonGenericSuccess = successResult; + Result nonGenericFailure = failureResult; + + // Assert + nonGenericSuccess.ShouldBeSuccess(); + nonGenericFailure.ShouldBeFailure(); + } + + [Fact] + public void ImplicitConversion_NonGenericResultToResult_WorksCorrectly() + { + // Arrange + var nonGenericSuccess = Result.Success().WithMessage("Success"); + var nonGenericFailure = Result.Failure().WithMessage("Failure"); + + // Act + Result successResult = nonGenericSuccess; + Result failureResult = nonGenericFailure; + + // Assert + successResult.ShouldBeSuccess(); + successResult.ShouldContainMessage("Success"); + + failureResult.ShouldBeFailure(); + failureResult.ShouldContainMessage("Failure"); + } + + [Fact] + public void ForConversion_ResultToResultOfDifferentType_WorksCorrectly() + { + // Arrange + var successResult = Result.Success(42).WithMessage("Success"); + var failureResult = Result.Failure().WithMessage("Failure").WithError(new Error("Test error")); + + // Act + // ReSharper disable once SuggestVarOrType_Elsewhere + Result convertedSuccessResult = successResult.For(); + // ReSharper disable once SuggestVarOrType_Elsewhere + Result convertedFailureResult = failureResult.For(); + + // Assert + convertedSuccessResult.ShouldBeSuccess(); + convertedSuccessResult.ShouldContainMessage("Success"); + + convertedFailureResult.ShouldBeFailure(); + convertedFailureResult.ShouldContainMessage("Failure"); + convertedFailureResult.ShouldContainError(); + } } \ No newline at end of file