├── .dockerignore ├── .editorconfig ├── .gitattributes ├── .gitignore ├── .markdownlint.json ├── CSharpFunctionalExtensions.Examples ├── CSharpFunctionalExtensions.Examples.csproj └── ResultExtensions │ ├── AsyncUsageExamples.cs │ ├── ExampleFromPluralsightCourse.cs │ ├── ExampleWithOnFailureMethod.cs │ ├── Methods │ └── BindZipExamples.cs │ ├── PassingResultThroughOnSuccessMethods.cs │ └── TapExamples.cs ├── CSharpFunctionalExtensions.StrongName ├── CSharpFunctionalExtensions.StrongName.csproj └── CSharpFunctionalExtensions.snk ├── CSharpFunctionalExtensions.Tests ├── CSharpFunctionalExtensions.Tests.csproj ├── EntityTests │ ├── BasicTests.cs │ └── IComparableTests.cs ├── MaybeTests │ ├── BasicTests.cs │ ├── BugTests.cs │ ├── EqualityTests.cs │ ├── Extensions │ │ ├── AsMaybeTests.Task.cs │ │ ├── AsMaybeTests.ValueTask.cs │ │ ├── AsMaybeTests.cs │ │ ├── AsNullableTests.cs │ │ ├── BindOptionalTests.cs │ │ ├── BindTests.Task.Left.cs │ │ ├── BindTests.Task.Right.cs │ │ ├── BindTests.Task.cs │ │ ├── BindTests.ValueTask.Left.cs │ │ ├── BindTests.ValueTask.Right.cs │ │ ├── BindTests.ValueTask.cs │ │ ├── BindTests.cs │ │ ├── ChooseTests.cs │ │ ├── ExecuteNoValueTests.Task.Left.cs │ │ ├── ExecuteNoValueTests.Task.Right.cs │ │ ├── ExecuteNoValueTests.Task.cs │ │ ├── ExecuteNoValueTests.ValueTask.Left.cs │ │ ├── ExecuteNoValueTests.ValueTask.Right.cs │ │ ├── ExecuteNoValueTests.ValueTask.cs │ │ ├── ExecuteNoValueTests.cs │ │ ├── ExecuteTests.Task.Left.cs │ │ ├── ExecuteTests.Task.Right.cs │ │ ├── ExecuteTests.Task.cs │ │ ├── ExecuteTests.ValueTask.Left.cs │ │ ├── ExecuteTests.ValueTask.Right.cs │ │ ├── ExecuteTests.ValueTask.cs │ │ ├── ExecuteTests.cs │ │ ├── GetValueOrDefaultTests.cs │ │ ├── GetValueOrThrowTests.Task.cs │ │ ├── GetValueOrThrowTests.ValueTask.cs │ │ ├── GetValueOrThrowTests.cs │ │ ├── MapTests.Task.Left.cs │ │ ├── MapTests.Task.Right.cs │ │ ├── MapTests.Task.cs │ │ ├── MapTests.ValueTask.Left.cs │ │ ├── MapTests.ValueTask.Right.cs │ │ ├── MapTests.ValueTask.cs │ │ ├── MapTests.cs │ │ ├── MatchTests.Task.cs │ │ ├── MatchTests.ValueTask.cs │ │ ├── MatchTests.cs │ │ ├── MaybeTestBase.cs │ │ ├── OptionalTests.cs │ │ ├── OrTests.Task.Left.cs │ │ ├── OrTests.Task.Right.cs │ │ ├── OrTests.Task.cs │ │ ├── OrTests.ValueTask.Left.cs │ │ ├── OrTests.ValueTask.Right.cs │ │ ├── OrTests.ValueTask.cs │ │ ├── OrTests.cs │ │ ├── SelectMany.cs │ │ ├── SelectTests.cs │ │ ├── ToInvertedResultTests.Task.cs │ │ ├── ToInvertedResultTests.ValueTask.cs │ │ ├── ToInvertedResultTests.cs │ │ ├── ToListTest.cs │ │ ├── ToResultTests.Task.cs │ │ ├── ToResultTests.ValueTask.cs │ │ ├── ToResultTests.cs │ │ ├── ToUnitResultTests.Task.cs │ │ ├── ToUnitResultTests.ValueTask.cs │ │ ├── ToUnitResultTests.cs │ │ ├── TryFindTests.cs │ │ ├── TryFirstTest.cs │ │ ├── TryLastTests.cs │ │ ├── WhereTests.Task.Left.cs │ │ ├── WhereTests.Task.Right.cs │ │ ├── WhereTests.Task.cs │ │ ├── WhereTests.ValueTask.Left.cs │ │ ├── WhereTests.ValueTask.Right.cs │ │ ├── WhereTests.ValueTask.cs │ │ └── WhereTests.cs │ └── ImplicitConversionTests.cs ├── NonParallelTestCollectionAttribute.cs ├── ResultTests │ ├── AmbiguityTests.cs │ ├── DeconstructionTests.cs │ ├── Extensions │ │ ├── AsMaybeTests.cs │ │ ├── BindIfTests.Base.cs │ │ ├── BindIfTests.Task.Left.cs │ │ ├── BindIfTests.Task.Right.cs │ │ ├── BindIfTests.Task.cs │ │ ├── BindIfTests.ValueTask.Left.cs │ │ ├── BindIfTests.ValueTask.Right.cs │ │ ├── BindIfTests.ValueTask.cs │ │ ├── BindIfTests.cs │ │ ├── BindOptionalTests.cs │ │ ├── BindTests.Base.cs │ │ ├── BindTests.Task.cs │ │ ├── BindTests.ValueTask.cs │ │ ├── BindTests.cs │ │ ├── BindTryTests.Base.cs │ │ ├── BindTryTests.Task.Left.cs │ │ ├── BindTryTests.Task.Right.cs │ │ ├── BindTryTests.Task.cs │ │ ├── BindTryTests.ValueTask.Left.cs │ │ ├── BindTryTests.ValueTask.Right.cs │ │ ├── BindTryTests.ValueTask.cs │ │ ├── BindTryTests.cs │ │ ├── BindZipTests.cs │ │ ├── BindsTests.Task.Left.cs │ │ ├── BindsTests.Task.Right.cs │ │ ├── BindsTests.ValueTask.Left.cs │ │ ├── BindsTests.ValueTask.Right.cs │ │ ├── CheckIfTests.Base.cs │ │ ├── CheckIfTests.Task.Left.cs │ │ ├── CheckIfTests.Task.Right.cs │ │ ├── CheckIfTests.Task.cs │ │ ├── CheckIfTests.ValueTask.Left.cs │ │ ├── CheckIfTests.ValueTask.Right.cs │ │ ├── CheckIfTests.ValueTask.cs │ │ ├── CheckIfTests.cs │ │ ├── CheckTests.Base.cs │ │ ├── CheckTests.Task.Left.cs │ │ ├── CheckTests.Task.Right.cs │ │ ├── CheckTests.Task.cs │ │ ├── CheckTests.ValueTask.Left.cs │ │ ├── CheckTests.ValueTask.Right.cs │ │ ├── CheckTests.ValueTask.cs │ │ ├── CheckTests.cs │ │ ├── CombineInOrderTests.cs │ │ ├── CompensateTests.Base.cs │ │ ├── CompensateTests.Task.Left.cs │ │ ├── CompensateTests.Task.Right.cs │ │ ├── CompensateTests.Task.cs │ │ ├── CompensateTests.ValueTask.Left.cs │ │ ├── CompensateTests.ValueTask.Right.cs │ │ ├── CompensateTests.ValueTask.cs │ │ ├── CompensateTests.cs │ │ ├── EnsureNotNullTests.Base.cs │ │ ├── EnsureNotNullTests.Task.Left.cs │ │ ├── EnsureNotNullTests.Task.Right.cs │ │ ├── EnsureNotNullTests.Task.cs │ │ ├── EnsureNotNullTests.ValueTask.Left.cs │ │ ├── EnsureNotNullTests.ValueTask.Right.cs │ │ ├── EnsureNotNullTests.ValueTask.cs │ │ ├── EnsureNotNullTests.cs │ │ ├── EnsureNotTests.cs │ │ ├── EnsureTests.Task.Left.cs │ │ ├── EnsureTests.Task.Right.cs │ │ ├── EnsureTests.Task.cs │ │ ├── EnsureTests.ValueTask.Left.cs │ │ ├── EnsureTests.ValueTask.Right.cs │ │ ├── EnsureTests.ValueTask.cs │ │ ├── EnsureTests.cs │ │ ├── FinallyTests.Base.cs │ │ ├── FinallyTests.Task.Left.cs │ │ ├── FinallyTests.Task.Right.cs │ │ ├── FinallyTests.Task.cs │ │ ├── FinallyTests.ValueTask.Left.cs │ │ ├── FinallyTests.ValueTask.Right.cs │ │ ├── FinallyTests.ValueTask.cs │ │ ├── FinallyTests.cs │ │ ├── GetValueOrDefaultTests.cs │ │ ├── MapErrorTests.Task.Left.cs │ │ ├── MapErrorTests.Task.Right.cs │ │ ├── MapErrorTests.Task.cs │ │ ├── MapErrorTests.ValueTask.Left.cs │ │ ├── MapErrorTests.ValueTask.Right.cs │ │ ├── MapErrorTests.ValueTask.cs │ │ ├── MapErrorTests.cs │ │ ├── MapIfTests.Base.cs │ │ ├── MapIfTests.Task.Left.cs │ │ ├── MapIfTests.Task.Right.cs │ │ ├── MapIfTests.Task.cs │ │ ├── MapIfTests.ValueTask.Left.cs │ │ ├── MapIfTests.ValueTask.Right.cs │ │ ├── MapIfTests.ValueTask.cs │ │ ├── MapIfTests.cs │ │ ├── MapTests.Base.cs │ │ ├── MapTests.Task.Left.cs │ │ ├── MapTests.Task.Right.cs │ │ ├── MapTests.Task.cs │ │ ├── MapTests.ValueTask.Left.cs │ │ ├── MapTests.ValueTask.Right.cs │ │ ├── MapTests.ValueTask.cs │ │ ├── MapTests.cs │ │ ├── MapTryTests.Base.cs │ │ ├── MapTryTests.Task.Left.cs │ │ ├── MapTryTests.Task.Right.cs │ │ ├── MapTryTests.Task.cs │ │ ├── MapTryTests.ValueTask.Left.cs │ │ ├── MapTryTests.ValueTask.Right.cs │ │ ├── MapTryTests.ValueTask.cs │ │ ├── MapTryTests.cs │ │ ├── MatchTests.Base.cs │ │ ├── MatchTests.Task.Left.cs │ │ ├── MatchTests.Task.Right.cs │ │ ├── MatchTests.Task.cs │ │ ├── MatchTests.ValueTask.Left.cs │ │ ├── MatchTests.ValueTask.Right.cs │ │ ├── MatchTests.ValueTask.cs │ │ ├── MatchTests.cs │ │ ├── NullableExtensionTests.cs │ │ ├── OnFailureCompensateTests.Task.Left.cs │ │ ├── OnFailureCompensateTests.Task.Right.cs │ │ ├── OnFailureCompensateTests.Task.cs │ │ ├── OnFailureCompensateTests.ValueTask.Left.cs │ │ ├── OnFailureCompensateTests.ValueTask.Right.cs │ │ ├── OnFailureCompensateTests.ValueTask.cs │ │ ├── OnFailureCompensateTests.cs │ │ ├── RequiredTests.cs │ │ ├── SelectTests.cs │ │ ├── TapErrorIfTests.Base.cs │ │ ├── TapErrorIfTests.Task.Left.cs │ │ ├── TapErrorIfTests.Task.Right.cs │ │ ├── TapErrorIfTests.Task.cs │ │ ├── TapErrorIfTests.ValueTask.Left.cs │ │ ├── TapErrorIfTests.ValueTask.Right.cs │ │ ├── TapErrorIfTests.ValueTask.cs │ │ ├── TapErrorIfTests.cs │ │ ├── TapErrorTests.Base.cs │ │ ├── TapErrorTests.Task.Left.cs │ │ ├── TapErrorTests.Task.Right.cs │ │ ├── TapErrorTests.Task.cs │ │ ├── TapErrorTests.ValueTask.Left.cs │ │ ├── TapErrorTests.ValueTask.Right.cs │ │ ├── TapErrorTests.ValueTask.cs │ │ ├── TapErrorTests.cs │ │ ├── TapIfTests.Base.cs │ │ ├── TapIfTests.Task.Left.cs │ │ ├── TapIfTests.Task.Right.cs │ │ ├── TapIfTests.Task.cs │ │ ├── TapIfTests.Value.Task.Left.cs │ │ ├── TapIfTests.Value.Task.Right.cs │ │ ├── TapIfTests.Value.Task.cs │ │ ├── TapIfTests.cs │ │ ├── TapTests.Base.cs │ │ ├── TapTests.Task.Left.cs │ │ ├── TapTests.Task.Right.cs │ │ ├── TapTests.Task.cs │ │ ├── TapTests.ValueTask.Left.cs │ │ ├── TapTests.ValueTask.Right.cs │ │ ├── TapTests.ValueTask.cs │ │ ├── TapTests.cs │ │ └── TapTryTests.cs │ ├── ImplicitConversionTests.cs │ ├── Json │ │ └── Serialization │ │ │ ├── HttpResponseMessageJsonExtensionsTests.cs │ │ │ └── SerializationTests.cs │ ├── Methods │ │ ├── CombineTests.cs │ │ ├── CombineWithErrorTests.cs │ │ ├── ConvertFailureTests.cs │ │ ├── FailedResultTests.cs │ │ ├── FirstFailureOrSuccessTests.cs │ │ ├── OfTests.cs │ │ ├── SucceededResultTests.cs │ │ ├── SuccessIfTests.cs │ │ ├── TryGetTests.cs │ │ ├── TryTaskTest.Base.cs │ │ ├── TryTest.Base.Common.cs │ │ ├── TryTest.Base.cs │ │ ├── TryTests.Task.cs │ │ ├── TryTests.cs │ │ └── TryValueTaskTest.Base.cs │ ├── ResultTests.cs │ ├── SerializationTests.cs │ ├── TestBase.cs │ └── ToStringTests.cs ├── TaskExtensions.cs ├── ValueObjectTests │ ├── AnotherTestEnumValueObject.cs │ ├── BasicTests.cs │ ├── EnumValueObjectTests.cs │ ├── IComparableTests.cs │ └── TestEnumValueObject.cs └── ValueTaskExtensions.cs ├── CSharpFunctionalExtensions.sln ├── CSharpFunctionalExtensions ├── CSharpFunctionalExtensions.csproj ├── Entity │ └── Entity.cs ├── ICombine.cs ├── Maybe │ ├── Extensions │ │ ├── AsMaybe.Task.cs │ │ ├── AsMaybe.ValueTask.cs │ │ ├── AsMaybe.cs │ │ ├── AsNullable.cs │ │ ├── Bind.Task.Left.cs │ │ ├── Bind.Task.Right.cs │ │ ├── Bind.Task.cs │ │ ├── Bind.ValueTask.Left.cs │ │ ├── Bind.ValueTask.Right.cs │ │ ├── Bind.ValueTask.cs │ │ ├── Bind.cs │ │ ├── BindOptional.cs │ │ ├── Choose.cs │ │ ├── Deconstruct.cs │ │ ├── Execute.Task.Left.cs │ │ ├── Execute.Task.Right.cs │ │ ├── Execute.Task.cs │ │ ├── Execute.ValueTask.Left.cs │ │ ├── Execute.ValueTask.Right.cs │ │ ├── Execute.ValueTask.cs │ │ ├── Execute.cs │ │ ├── ExecuteNoValue.Task.Left.cs │ │ ├── ExecuteNoValue.Task.Right.cs │ │ ├── ExecuteNoValue.Task.cs │ │ ├── ExecuteNoValue.ValueTask.Left.cs │ │ ├── ExecuteNoValue.ValueTask.Right.cs │ │ ├── ExecuteNoValue.ValueTask.cs │ │ ├── ExecuteNoValue.cs │ │ ├── Flatten.cs │ │ ├── GetValueOrDefault.Task.Left.cs │ │ ├── GetValueOrDefault.Task.Right.cs │ │ ├── GetValueOrDefault.Task.cs │ │ ├── GetValueOrDefault.ValueTask.Left.cs │ │ ├── GetValueOrDefault.ValueTask.Right.cs │ │ ├── GetValueOrDefault.ValueTask.cs │ │ ├── GetValueOrDefault.cs │ │ ├── GetValueOrThrow.Task.cs │ │ ├── GetValueOrThrow.ValueTask.cs │ │ ├── Map.Task.Left.cs │ │ ├── Map.Task.Right.cs │ │ ├── Map.Task.cs │ │ ├── Map.ValueTask.Left.cs │ │ ├── Map.ValueTask.Right.cs │ │ ├── Map.ValueTask.cs │ │ ├── Map.cs │ │ ├── Match.Task.cs │ │ ├── Match.ValueTask.cs │ │ ├── Match.cs │ │ ├── Optional.cs │ │ ├── Or.Task.Left.cs │ │ ├── Or.Task.Right.cs │ │ ├── Or.Task.cs │ │ ├── Or.ValueTask.Left.cs │ │ ├── Or.ValueTask.Right.cs │ │ ├── Or.ValueTask.cs │ │ ├── Or.cs │ │ ├── Select.cs │ │ ├── SelectMany.cs │ │ ├── ToInvertedResult.Task.cs │ │ ├── ToInvertedResult.ValueTask.cs │ │ ├── ToInvertedResult.cs │ │ ├── ToList.cs │ │ ├── ToResult.Task.cs │ │ ├── ToResult.ValueTask.cs │ │ ├── ToResult.cs │ │ ├── ToUnitResult.Task.cs │ │ ├── ToUnitResult.ValueTask.cs │ │ ├── ToUnitResult.cs │ │ ├── TryFind.cs │ │ ├── TryFirst.cs │ │ ├── TryLast.cs │ │ ├── Where.Task.Left.cs │ │ ├── Where.Task.Right.cs │ │ ├── Where.Task.cs │ │ ├── Where.ValueTask.Left.cs │ │ ├── Where.ValueTask.Right.cs │ │ ├── Where.ValueTask.cs │ │ └── Where.cs │ ├── Maybe.Configuration.cs │ ├── Maybe.cs │ └── MaybeEqualityComparer.cs ├── Result │ ├── Exceptions │ │ ├── ResultFailureException.cs │ │ └── ResultSuccessException.cs │ ├── IResult.cs │ ├── Internal │ │ ├── Result.Messages.cs │ │ ├── ResultCommonLogic.cs │ │ ├── SerializationValue.cs │ │ ├── TaskExtensions.cs │ │ └── ValueTaskExtensions.cs │ ├── Json │ │ └── Serialization │ │ │ ├── CSharpFunctionalExtensionsJsonSerializerOptions.cs │ │ │ ├── DtoMessages.cs │ │ │ ├── HttpResponseMessageJsonExtensions.cs │ │ │ ├── JsonSerializerOptionsExtensionMethods.cs │ │ │ ├── ResultDto.cs │ │ │ ├── ResultJsonConverter.cs │ │ │ ├── ResultJsonOfTConverter.cs │ │ │ ├── ResultOfTEJsonConverterFactory.cs │ │ │ ├── UnitResultDto.cs │ │ │ └── UnitResultJsonConverterFactoryOfT.cs │ ├── Methods │ │ ├── Combine.cs │ │ ├── ConvertFailure.cs │ │ ├── Extensions │ │ │ ├── AsMaybe.cs │ │ │ ├── Bind.Task.Left.cs │ │ │ ├── Bind.Task.Right.cs │ │ │ ├── Bind.Task.cs │ │ │ ├── Bind.ValueTask.Left.cs │ │ │ ├── Bind.ValueTask.Right.cs │ │ │ ├── Bind.ValueTask.cs │ │ │ ├── Bind.cs │ │ │ ├── BindIf.Task.Left.cs │ │ │ ├── BindIf.Task.Right.cs │ │ │ ├── BindIf.Task.cs │ │ │ ├── BindIf.ValueTask.Left.cs │ │ │ ├── BindIf.ValueTask.Right.cs │ │ │ ├── BindIf.ValueTask.cs │ │ │ ├── BindIf.cs │ │ │ ├── BindOptional.cs │ │ │ ├── BindTry.Task.Left.cs │ │ │ ├── BindTry.Task.Right.cs │ │ │ ├── BindTry.Task.cs │ │ │ ├── BindTry.ValueTask.Left.cs │ │ │ ├── BindTry.ValueTask.Right.cs │ │ │ ├── BindTry.ValueTask.cs │ │ │ ├── BindTry.cs │ │ │ ├── BindWithTransactionScope.Task.Left.cs │ │ │ ├── BindWithTransactionScope.Task.Right.cs │ │ │ ├── BindWithTransactionScope.Task.cs │ │ │ ├── BindWithTransactionScope.ValueTask.Left.cs │ │ │ ├── BindWithTransactionScope.ValueTask.Right.cs │ │ │ ├── BindWithTransactionScope.ValueTask.cs │ │ │ ├── BindWithTransactionScope.cs │ │ │ ├── BindZip.Task.Left.cs │ │ │ ├── BindZip.Task.Right.cs │ │ │ ├── BindZip.Task.cs │ │ │ ├── BindZip.cs │ │ │ ├── Check.Task.Left.cs │ │ │ ├── Check.Task.Right.cs │ │ │ ├── Check.Task.cs │ │ │ ├── Check.ValueTask.Left.cs │ │ │ ├── Check.ValueTask.Right.cs │ │ │ ├── Check.ValueTask.cs │ │ │ ├── Check.cs │ │ │ ├── CheckIf.Task.Left.cs │ │ │ ├── CheckIf.Task.Right.cs │ │ │ ├── CheckIf.Task.cs │ │ │ ├── CheckIf.ValueTask.Left.cs │ │ │ ├── CheckIf.ValueTask.Right.cs │ │ │ ├── CheckIf.ValueTask.cs │ │ │ ├── CheckIf.cs │ │ │ ├── Combine.Task.cs │ │ │ ├── Combine.ValueTask.cs │ │ │ ├── Combine.cs │ │ │ ├── CombineInOrder.Task.cs │ │ │ ├── CombineInOrder.ValueTask.cs │ │ │ ├── Compensate.Task.Left.cs │ │ │ ├── Compensate.Task.Right.cs │ │ │ ├── Compensate.Task.cs │ │ │ ├── Compensate.ValueTask.Left.cs │ │ │ ├── Compensate.ValueTask.Right.cs │ │ │ ├── Compensate.ValueTask.cs │ │ │ ├── Compensate.cs │ │ │ ├── Deconstruct.cs │ │ │ ├── Ensure.Task.Left.cs │ │ │ ├── Ensure.Task.Right.cs │ │ │ ├── Ensure.Task.cs │ │ │ ├── Ensure.ValueTask.Left.cs │ │ │ ├── Ensure.ValueTask.Right.cs │ │ │ ├── Ensure.ValueTask.cs │ │ │ ├── Ensure.cs │ │ │ ├── EnsureNot.cs │ │ │ ├── EnsureNotNull.Task.Left.cs │ │ │ ├── EnsureNotNull.Task.Right.cs │ │ │ ├── EnsureNotNull.Task.cs │ │ │ ├── EnsureNotNull.ValueTask.Left.cs │ │ │ ├── EnsureNotNull.ValueTask.Right.cs │ │ │ ├── EnsureNotNull.ValueTask.cs │ │ │ ├── EnsureNotNull.cs │ │ │ ├── Finally.Task.Left.cs │ │ │ ├── Finally.Task.Right.cs │ │ │ ├── Finally.Task.cs │ │ │ ├── Finally.ValueTask.Left.cs │ │ │ ├── Finally.ValueTask.Right.cs │ │ │ ├── Finally.ValueTask.cs │ │ │ ├── Finally.cs │ │ │ ├── GetValueOrDefault.Task.Left.cs │ │ │ ├── GetValueOrDefault.Task.Right.cs │ │ │ ├── GetValueOrDefault.Task.cs │ │ │ ├── GetValueOrDefault.ValueTask.Left.cs │ │ │ ├── GetValueOrDefault.ValueTask.Right.cs │ │ │ ├── GetValueOrDefault.ValueTask.cs │ │ │ ├── GetValueOrDefault.cs │ │ │ ├── Map.Task.Left.cs │ │ │ ├── Map.Task.Right.cs │ │ │ ├── Map.Task.cs │ │ │ ├── Map.ValueTask.Left.cs │ │ │ ├── Map.ValueTask.Right.cs │ │ │ ├── Map.ValueTask.cs │ │ │ ├── Map.cs │ │ │ ├── MapError.Task.Left.cs │ │ │ ├── MapError.Task.Right.cs │ │ │ ├── MapError.Task.cs │ │ │ ├── MapError.ValueTask.Left.cs │ │ │ ├── MapError.ValueTask.Right.cs │ │ │ ├── MapError.ValueTask.cs │ │ │ ├── MapError.cs │ │ │ ├── MapIf.Task.Left.cs │ │ │ ├── MapIf.Task.Right.cs │ │ │ ├── MapIf.Task.cs │ │ │ ├── MapIf.ValueTask.Left.cs │ │ │ ├── MapIf.ValueTask.Right.cs │ │ │ ├── MapIf.ValueTask.cs │ │ │ ├── MapIf.cs │ │ │ ├── MapTry.Task.Left.cs │ │ │ ├── MapTry.Task.Right.cs │ │ │ ├── MapTry.Task.cs │ │ │ ├── MapTry.ValueTask.Left.cs │ │ │ ├── MapTry.ValueTask.Right.cs │ │ │ ├── MapTry.ValueTask.cs │ │ │ ├── MapTry.cs │ │ │ ├── MapWithTransactionScope.Task.Left.cs │ │ │ ├── MapWithTransactionScope.Task.Right.cs │ │ │ ├── MapWithTransactionScope.Task.cs │ │ │ ├── MapWithTransactionScope.ValueTask.Left.cs │ │ │ ├── MapWithTransactionScope.ValueTask.Right.cs │ │ │ ├── MapWithTransactionScope.ValueTask.cs │ │ │ ├── MapWithTransactionScope.cs │ │ │ ├── Match.Task.Left.cs │ │ │ ├── Match.Task.Right.cs │ │ │ ├── Match.Task.cs │ │ │ ├── Match.ValueTask.Left.cs │ │ │ ├── Match.ValueTask.Right.cs │ │ │ ├── Match.ValueTask.cs │ │ │ ├── Match.cs │ │ │ ├── OnFailureCompensate.Task.Left.cs │ │ │ ├── OnFailureCompensate.Task.Right.cs │ │ │ ├── OnFailureCompensate.Task.cs │ │ │ ├── OnFailureCompensate.ValueTask.Left.cs │ │ │ ├── OnFailureCompensate.ValueTask.Right.cs │ │ │ ├── OnFailureCompensate.ValueTask.cs │ │ │ ├── OnFailureCompensate.cs │ │ │ ├── OnSuccessTry.Task.Left.cs │ │ │ ├── OnSuccessTry.Task.Right.cs │ │ │ ├── OnSuccessTry.Task.cs │ │ │ ├── OnSuccessTry.cs │ │ │ ├── Required.cs │ │ │ ├── Select.cs │ │ │ ├── SelectMany.Task.Left.cs │ │ │ ├── SelectMany.Task.Right.cs │ │ │ ├── SelectMany.Task.cs │ │ │ ├── SelectMany.ValueTask.Left.cs │ │ │ ├── SelectMany.ValueTask.Right.cs │ │ │ ├── SelectMany.ValueTask.cs │ │ │ ├── SelectMany.cs │ │ │ ├── Tap.Task.Left.cs │ │ │ ├── Tap.Task.Right.cs │ │ │ ├── Tap.Task.cs │ │ │ ├── Tap.ValueTask.Left.cs │ │ │ ├── Tap.ValueTask.Right.cs │ │ │ ├── Tap.ValueTask.cs │ │ │ ├── Tap.cs │ │ │ ├── TapError.Task.Left.cs │ │ │ ├── TapError.Task.Right.cs │ │ │ ├── TapError.Task.cs │ │ │ ├── TapError.ValueTask.Left.cs │ │ │ ├── TapError.ValueTask.Right.cs │ │ │ ├── TapError.ValueTask.cs │ │ │ ├── TapError.cs │ │ │ ├── TapErrorIf.Task.Left.cs │ │ │ ├── TapErrorIf.Task.Right.cs │ │ │ ├── TapErrorIf.Task.cs │ │ │ ├── TapErrorIf.ValueTask.Left.cs │ │ │ ├── TapErrorIf.ValueTask.Right.cs │ │ │ ├── TapErrorIf.ValueTask.cs │ │ │ ├── TapErrorIf.cs │ │ │ ├── TapIf.Task.Left.cs │ │ │ ├── TapIf.Task.Right.cs │ │ │ ├── TapIf.Task.cs │ │ │ ├── TapIf.ValueTask.Left.cs │ │ │ ├── TapIf.ValueTask.Right.cs │ │ │ ├── TapIf.ValueTask.cs │ │ │ ├── TapIf.cs │ │ │ ├── TapIfTry.Task.Left.cs │ │ │ ├── TapIfTry.Task.Right.cs │ │ │ ├── TapIfTry.Task.cs │ │ │ ├── TapIfTry.cs │ │ │ ├── TapTry.Task.Left.cs │ │ │ ├── TapTry.Task.Right.cs │ │ │ ├── TapTry.Task.cs │ │ │ ├── TapTry.cs │ │ │ └── WithTransactionScope.cs │ │ ├── Failure.cs │ │ ├── FailureIf.Task.cs │ │ ├── FailureIf.ValueTask.cs │ │ ├── FailureIf.cs │ │ ├── FirstFailureOrSuccess.cs │ │ ├── Of.cs │ │ ├── Success.cs │ │ ├── SuccessIf.Task.cs │ │ ├── SuccessIf.ValueTask.cs │ │ ├── SuccessIf.cs │ │ ├── ToString.cs │ │ ├── Try.Task.cs │ │ ├── Try.cs │ │ └── TryGet.cs │ ├── NullableExtensions.cs │ ├── Result.Configuration.cs │ ├── Result.cs │ ├── ResultT.cs │ ├── ResultTE.cs │ └── UnitResult.cs └── ValueObject │ ├── ComparableValueObject.cs │ ├── EnumValueObject.cs │ ├── SimpleValueObject.cs │ ├── ValueObject.cs │ └── ValueObjectOfT.cs ├── Common.Build.props ├── Dockerfile ├── LICENSE ├── README.md ├── azure-pipelines.yml └── version.txt /.dockerignore: -------------------------------------------------------------------------------- 1 | **/.git/ 2 | **/.vs/ 3 | **/bin/ 4 | **/obj/ 5 | **/*ncrunch* 6 | **/out/ 7 | **/TestResults/ 8 | 9 | Dockerfile* 10 | nCrunchTemp* 11 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | .svn 3 | obj 4 | bin 5 | .idea 6 | _ReSharper* 7 | *.sln.GhostDoc.xml 8 | *.dotCover 9 | *.suo 10 | *.user 11 | *.Cache 12 | *.cache 13 | *.ncrunchsolution 14 | *.ncrunchproject 15 | /packages/*/* 16 | /Tools/*/* 17 | project.lock.json 18 | project.fragment.lock.json 19 | .vs 20 | /CSharpFunctionalExtensions/CSharpFunctionalExtensions.xml 21 | *ncrunch* 22 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "line-length": { 3 | "line_length": 140 4 | }, 5 | "code-block-style": { 6 | "style": "fenced" 7 | }, 8 | "code": true, 9 | "code-fence-style": true, 10 | "no-duplicate-header": { 11 | "siblings_only": true 12 | } 13 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Examples/CSharpFunctionalExtensions.Examples.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | 8.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Examples/ResultExtensions/ExampleFromPluralsightCourse.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpFunctionalExtensions.Examples.ResultExtensions 2 | { 3 | public class ExampleFromPluralsightCourse 4 | { 5 | public string Promote(long id) 6 | { 7 | var gateway = new EmailGateway(); 8 | 9 | return GetById(id) 10 | .ToResult("Customer with such Id is not found: " + id) 11 | .Ensure(customer => customer.CanBePromoted(), "The customer has the highest status possible") 12 | .Tap(customer => customer.Promote()) 13 | .Bind(customer => gateway.SendPromotionNotification(customer.Email)) 14 | .Finally(result => result.IsSuccess ? "Ok" : result.Error); 15 | } 16 | 17 | public Maybe GetById(long id) 18 | { 19 | return new Customer(); 20 | } 21 | 22 | public class Customer 23 | { 24 | public string Email { get; } 25 | 26 | public Customer() 27 | { 28 | } 29 | 30 | public bool CanBePromoted() 31 | { 32 | return true; 33 | } 34 | 35 | public void Promote() 36 | { 37 | } 38 | } 39 | 40 | public class EmailGateway 41 | { 42 | public Result SendPromotionNotification(string email) 43 | { 44 | return Result.Success(); 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Examples/ResultExtensions/Methods/BindZipExamples.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace CSharpFunctionalExtensions.Examples.ResultExtensions.Methods 4 | { 5 | public class BindZipExamples 6 | { 7 | public async Task BindZipAsyncSample() 8 | { 9 | await FetchFirstEntity() 10 | .BindZip(FetchSecondEntity) 11 | .Map(x => $"{x.First}, {x.Second}!"); 12 | 13 | return; 14 | 15 | Task> FetchFirstEntity() => 16 | Task.FromResult(Result.Success("Hello")); 17 | 18 | Result FetchSecondEntity(string _) => 19 | "World"; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Examples/ResultExtensions/PassingResultThroughOnSuccessMethods.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | 4 | namespace CSharpFunctionalExtensions.Examples.ResultExtensions 5 | { 6 | public class PassingResultThroughOnSuccessMethods 7 | { 8 | public void Example1() 9 | { 10 | Result result = FunctionInt() 11 | .Bind(x => FunctionString(x)) 12 | .Bind(x => FunctionDateTime(x)); 13 | } 14 | 15 | public void Example2() 16 | { 17 | Result result = FunctionInt() 18 | .Bind(_ => FunctionString()) 19 | .Bind(x => FunctionDateTime(x)); 20 | } 21 | 22 | private Result FunctionInt() 23 | { 24 | return Result.Success(1); 25 | } 26 | 27 | private Result FunctionString(int intValue) 28 | { 29 | return Result.Success("Ok"); 30 | } 31 | 32 | private Result FunctionString() 33 | { 34 | return Result.Success("Ok"); 35 | } 36 | 37 | private Result FunctionDateTime(string stringValue) 38 | { 39 | return Result.Success(DateTime.Now); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.StrongName/CSharpFunctionalExtensions.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vkhorikov/CSharpFunctionalExtensions/15a6158ce2b3e8d67315696e9d2d0693014ec906/CSharpFunctionalExtensions.StrongName/CSharpFunctionalExtensions.snk -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/AsMaybeTests.Task.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using CSharpFunctionalExtensions.Tests.ResultTests; 3 | using FluentAssertions; 4 | using Xunit; 5 | 6 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions; 7 | 8 | public class AsMaybeTests_Task : TestBase 9 | { 10 | [Fact] 11 | public async Task AsMaybe_Task_Struct_maybe_conversion_equality_none() 12 | { 13 | double? none = default; 14 | var maybeNone = await none.AsTask().AsMaybe(); 15 | maybeNone.HasValue.Should().Be(none.HasValue); 16 | } 17 | 18 | [Fact] 19 | public async Task AsMaybe_Task_Struct_maybe_conversion_equality_some() 20 | { 21 | double? some = 123; 22 | var someMaybe = await some.AsTask().AsMaybe(); 23 | someMaybe.HasValue.Should().Be(some.HasValue); 24 | someMaybe.Value.Should().Be(some); 25 | } 26 | 27 | [Fact] 28 | public async Task AsMaybe_Task_Class_maybe_conversion_none() 29 | { 30 | var maybeT = await Maybe.None.AsTask(); 31 | maybeT.HasValue.Should().BeFalse(); 32 | } 33 | 34 | [Fact] 35 | public async Task AsMaybe_Task_Class_maybe_conversion_some() 36 | { 37 | var maybeT = await T.Value.AsMaybe().AsTask(); 38 | maybeT.HasValue.Should().BeTrue(); 39 | maybeT.Value.Should().Be(T.Value); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/AsMaybeTests.ValueTask.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using CSharpFunctionalExtensions.Tests.ResultTests; 3 | using CSharpFunctionalExtensions.ValueTasks; 4 | using FluentAssertions; 5 | using Xunit; 6 | 7 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions; 8 | 9 | public class AsMaybeTests_ValueTask : TestBase 10 | { 11 | [Fact] 12 | public async Task AsMaybe_ValueTask_Struct_maybe_conversion_equality_none() 13 | { 14 | double? none = default; 15 | var maybeNone = await none.AsValueTask().AsMaybe(); 16 | maybeNone.HasValue.Should().Be(none.HasValue); 17 | } 18 | 19 | [Fact] 20 | public async Task AsMaybe_ValueTask_Struct_maybe_conversion_equality_some() 21 | { 22 | double? some = 123; 23 | var someMaybe = await some.AsValueTask().AsMaybe(); 24 | someMaybe.HasValue.Should().Be(some.HasValue); 25 | someMaybe.Value.Should().Be(some); 26 | } 27 | 28 | [Fact] 29 | public async Task AsMaybe_ValueTask_Class_maybe_conversion_none() 30 | { 31 | var maybeT = await Maybe.None.AsValueTask(); 32 | maybeT.HasValue.Should().BeFalse(); 33 | } 34 | 35 | [Fact] 36 | public async Task AsMaybe_ValueTask_Class_maybe_conversion_some() 37 | { 38 | var maybeT = await T.Value.AsValueTask().AsMaybe(); 39 | maybeT.HasValue.Should().BeTrue(); 40 | maybeT.Value.Should().Be(T.Value); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/AsMaybeTests.cs: -------------------------------------------------------------------------------- 1 | using CSharpFunctionalExtensions.Tests.ResultTests; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions; 6 | 7 | public class AsMaybeTests : TestBase 8 | { 9 | [Fact] 10 | public void AsMaybe_Struct_maybe_conversion_equality_none() 11 | { 12 | double? none = default; 13 | Maybe maybeNone = none.AsMaybe(); 14 | maybeNone.HasValue.Should().Be(none.HasValue); 15 | } 16 | 17 | [Fact] 18 | public void AsMaybe_Struct_maybe_conversion_equality_some() 19 | { 20 | double? some = 123; 21 | Maybe someMaybe = some.AsMaybe(); 22 | someMaybe.HasValue.Should().Be(some.HasValue); 23 | someMaybe.Value.Should().Be(some); 24 | } 25 | 26 | [Fact] 27 | public void AsMaybe_Class_maybe_conversion_none() 28 | { 29 | Maybe maybeT = null; 30 | maybeT.HasValue.Should().BeFalse(); 31 | } 32 | 33 | [Fact] 34 | public void AsMaybe_Class_maybe_conversion_some() 35 | { 36 | Maybe maybeT = T.Value.AsMaybe(); 37 | maybeT.HasValue.Should().BeTrue(); 38 | maybeT.Value.Should().Be(T.Value); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/AsNullableTests.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using Xunit; 3 | 4 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions; 5 | 6 | public class AsNullableTests 7 | { 8 | [Fact] 9 | public void Struct_nullable_conversion_equality_none() 10 | { 11 | Maybe none = default; 12 | double? noneNullable = none.AsNullable(); 13 | noneNullable.HasValue.Should().Be(none.HasValue); 14 | } 15 | 16 | [Fact] 17 | public void Struct_nullable_conversion_equality_some() 18 | { 19 | Maybe some = 123; 20 | double? someNullable = some.AsNullable(); 21 | someNullable.HasValue.Should().Be(some.HasValue); 22 | someNullable.Should().Be(some.Value); 23 | } 24 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/ChooseTests.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using Xunit; 3 | 4 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions; 5 | 6 | public class ChooseTests 7 | { 8 | [Fact] 9 | public void Choose_double_values() 10 | { 11 | var source = new[] 12 | { 13 | Maybe.None, 14 | 1, 15 | Maybe.None, 16 | 2, 17 | 3 18 | }; 19 | 20 | var doubled = source.Choose(x => x * 2); 21 | 22 | var expected = new[] { 2, 4, 6 }; 23 | doubled.Should().BeEquivalentTo(expected); 24 | } 25 | 26 | [Fact] 27 | public void Choose_values() 28 | { 29 | var source = new[] 30 | { 31 | Maybe.None, 32 | 1, 33 | Maybe.None, 34 | 2, 35 | 3 36 | }; 37 | 38 | var values = source.Choose(); 39 | 40 | var expected = new[] { 1, 2, 3 }; 41 | values.Should().BeEquivalentTo(expected); 42 | } 43 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/ExecuteNoValueTests.Task.Left.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 6 | { 7 | public class ExecuteNoValueTests_Task_Left : MaybeTestBase 8 | { 9 | [Fact] 10 | public async Task ExecuteNoValue_Task_Left_executes_action_when_no_value() 11 | { 12 | string property = null; 13 | 14 | Maybe maybe = null; 15 | 16 | await maybe.AsTask().ExecuteNoValue(() => property = "Some value"); 17 | 18 | property.Should().Be("Some value"); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/ExecuteNoValueTests.Task.Right.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 6 | { 7 | public class ExecuteNoValueTests_Task_Right : MaybeTestBase 8 | { 9 | [Fact] 10 | public async Task ExecuteNoValue_Task_Right_executes_action_when_no_value() 11 | { 12 | string property = null; 13 | 14 | Maybe maybe = null; 15 | 16 | await maybe.ExecuteNoValue(() => 17 | { 18 | property = "Some value"; 19 | return Task.CompletedTask; 20 | }); 21 | 22 | property.Should().Be("Some value"); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/ExecuteNoValueTests.Task.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 6 | { 7 | public class ExecuteNoValueTests_Task : MaybeTestBase 8 | { 9 | [Fact] 10 | public async Task ExecuteNoValue_Task_executes_action_when_no_value() 11 | { 12 | string property = null; 13 | 14 | Maybe maybe = null; 15 | 16 | await maybe.AsTask().ExecuteNoValue(() => 17 | { 18 | property = "Some value"; 19 | return Task.CompletedTask; 20 | }); 21 | 22 | property.Should().Be("Some value"); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/ExecuteNoValueTests.ValueTask.Left.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using CSharpFunctionalExtensions.ValueTasks; 3 | using FluentAssertions; 4 | using Xunit; 5 | 6 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 7 | { 8 | public class ExecuteNoValueTests_ValueTask_Left : MaybeTestBase 9 | { 10 | [Fact] 11 | public async Task ExecuteNoValue_ValueTask_Left_executes_action_when_no_value() 12 | { 13 | string property = null; 14 | 15 | Maybe maybe = null; 16 | 17 | await maybe.AsValueTask().ExecuteNoValue(() => property = "Some value"); 18 | 19 | property.Should().Be("Some value"); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/ExecuteNoValueTests.ValueTask.Right.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using CSharpFunctionalExtensions.ValueTasks; 3 | using FluentAssertions; 4 | using Xunit; 5 | 6 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 7 | { 8 | public class ExecuteNoValueTests_ValueTask_Right : MaybeTestBase 9 | { 10 | [Fact] 11 | public async Task ExecuteNoValue_ValueTask_Right_executes_action_when_no_value() 12 | { 13 | string property = null; 14 | 15 | Maybe maybe = null; 16 | 17 | await maybe.ExecuteNoValue(() => 18 | { 19 | property = "Some value"; 20 | return ValueTask.CompletedTask; 21 | }); 22 | 23 | property.Should().Be("Some value"); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/ExecuteNoValueTests.ValueTask.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using CSharpFunctionalExtensions.ValueTasks; 3 | using FluentAssertions; 4 | using Xunit; 5 | 6 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 7 | { 8 | public class ExecuteNoValueTests_ValueTask : MaybeTestBase 9 | { 10 | [Fact] 11 | public async Task ExecuteNoValue_ValueTask_executes_action_when_no_value() 12 | { 13 | string property = null; 14 | 15 | Maybe maybe = null; 16 | 17 | await maybe.AsValueTask().ExecuteNoValue(() => 18 | { 19 | property = "Some value"; 20 | return ValueTask.CompletedTask; 21 | }); 22 | 23 | property.Should().Be("Some value"); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/ExecuteNoValueTests.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using Xunit; 3 | 4 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 5 | { 6 | public class ExecuteNoValueTests : MaybeTestBase 7 | { 8 | [Fact] 9 | public void ExecuteNoValue_executes_action_when_no_value() 10 | { 11 | string property = null; 12 | 13 | Maybe maybe = null; 14 | 15 | maybe.ExecuteNoValue(() => property = "Some value"); 16 | 17 | property.Should().Be("Some value"); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/ExecuteTests.Task.Left.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 6 | { 7 | public class ExecuteTests_Task_Left : MaybeTestBase 8 | { 9 | [Fact] 10 | public async Task Execute_Task_Lef_does_not_execute_action_if_no_value() 11 | { 12 | Maybe instance = null; 13 | 14 | await instance.AsTask().Execute(value => instance = T.Value); 15 | 16 | instance.HasNoValue.Should().BeTrue(); 17 | } 18 | 19 | [Fact] 20 | public async Task Execute_Task_Lef_executes_action_if_value() 21 | { 22 | Maybe instance = T.Value; 23 | 24 | await instance.AsTask().Execute(value => value.Should().Be(T.Value)); 25 | 26 | instance.Value.Should().Be(T.Value); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/ExecuteTests.Task.Right.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 6 | { 7 | public class ExecuteTests_Task_Right : MaybeTestBase 8 | { 9 | [Fact] 10 | public async Task Execute_Task_Right_does_not_execute_action_if_no_value() 11 | { 12 | Maybe instance = null; 13 | 14 | await instance.Execute(value => 15 | { 16 | instance = T.Value; 17 | return Task.CompletedTask; 18 | }); 19 | 20 | instance.HasNoValue.Should().BeTrue(); 21 | } 22 | 23 | [Fact] 24 | public async Task Execute_Task_Right_executes_action_if_value() 25 | { 26 | Maybe instance = T.Value; 27 | 28 | await instance.Execute(value => 29 | { 30 | value.Should().Be(T.Value); 31 | return Task.CompletedTask; 32 | }); 33 | 34 | instance.Value.Should().Be(T.Value); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/ExecuteTests.Task.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 6 | { 7 | public class ExecuteTests_Task : MaybeTestBase 8 | { 9 | [Fact] 10 | public async Task Execute_Task_does_not_execute_action_if_no_value() 11 | { 12 | Maybe instance = null; 13 | 14 | await instance.AsTask().Execute(value => 15 | { 16 | instance = T.Value; 17 | return Task.CompletedTask; 18 | }); 19 | 20 | instance.HasNoValue.Should().BeTrue(); 21 | } 22 | 23 | [Fact] 24 | public async Task Execute_Task_executes_action_if_value() 25 | { 26 | Maybe instance = T.Value; 27 | 28 | await instance.AsTask().Execute(value => 29 | { 30 | value.Should().Be(T.Value); 31 | return Task.CompletedTask; 32 | }); 33 | 34 | instance.Value.Should().Be(T.Value); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/ExecuteTests.ValueTask.Left.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using CSharpFunctionalExtensions.ValueTasks; 3 | using FluentAssertions; 4 | using Xunit; 5 | 6 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 7 | { 8 | public class ExecuteTests_ValueTask_Left : MaybeTestBase 9 | { 10 | [Fact] 11 | public async Task Execute_ValueTask_Lef_does_not_execute_action_if_no_value() 12 | { 13 | Maybe instance = null; 14 | 15 | await instance.AsValueTask().Execute(value => instance = T.Value); 16 | 17 | instance.HasNoValue.Should().BeTrue(); 18 | } 19 | 20 | [Fact] 21 | public async Task Execute_ValueTask_Lef_executes_action_if_value() 22 | { 23 | Maybe instance = T.Value; 24 | 25 | await instance.AsValueTask().Execute(value => value.Should().Be(T.Value)); 26 | 27 | instance.Value.Should().Be(T.Value); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/ExecuteTests.ValueTask.Right.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using CSharpFunctionalExtensions.ValueTasks; 3 | using FluentAssertions; 4 | using Xunit; 5 | 6 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 7 | { 8 | public class ExecuteTests_ValueTask_Right : MaybeTestBase 9 | { 10 | [Fact] 11 | public async Task Execute_ValueTask_Right_does_not_execute_action_if_no_value() 12 | { 13 | Maybe instance = null; 14 | 15 | await instance.Execute(value => 16 | { 17 | instance = T.Value; 18 | return ValueTask.CompletedTask; 19 | }); 20 | 21 | instance.HasNoValue.Should().BeTrue(); 22 | } 23 | 24 | [Fact] 25 | public async Task Execute_ValueTask_Right_executes_action_if_value() 26 | { 27 | Maybe instance = T.Value; 28 | 29 | await instance.Execute(value => 30 | { 31 | value.Should().Be(T.Value); 32 | return ValueTask.CompletedTask; 33 | }); 34 | 35 | instance.Value.Should().Be(T.Value); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/ExecuteTests.ValueTask.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using CSharpFunctionalExtensions.ValueTasks; 3 | using FluentAssertions; 4 | using Xunit; 5 | 6 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 7 | { 8 | public class ExecuteTests_ValueTask : MaybeTestBase 9 | { 10 | [Fact] 11 | public async Task Execute_ValueTask_does_not_execute_action_if_no_value() 12 | { 13 | Maybe instance = null; 14 | 15 | await instance.AsValueTask().Execute(value => 16 | { 17 | instance = T.Value; 18 | return ValueTask.CompletedTask; 19 | }); 20 | 21 | instance.HasNoValue.Should().BeTrue(); 22 | } 23 | 24 | [Fact] 25 | public async Task Execute_ValueTask_executes_action_if_value() 26 | { 27 | Maybe instance = T.Value; 28 | 29 | await instance.AsValueTask().Execute(value => 30 | { 31 | value.Should().Be(T.Value); 32 | return ValueTask.CompletedTask; 33 | }); 34 | 35 | instance.Value.Should().Be(T.Value); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/ExecuteTests.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using Xunit; 3 | 4 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 5 | { 6 | public class ExecuteTests : MaybeTestBase 7 | { 8 | [Fact] 9 | public void Execute_does_not_execute_action_if_no_value() 10 | { 11 | Maybe instance = null; 12 | 13 | instance.Execute(value => instance = T.Value); 14 | 15 | instance.HasNoValue.Should().BeTrue(); 16 | } 17 | 18 | [Fact] 19 | public void Execute_executes_action_if_value() 20 | { 21 | Maybe instance = T.Value; 22 | 23 | instance.Execute(value => value.Should().Be(T.Value)); 24 | 25 | instance.Value.Should().Be(T.Value); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/GetValueOrDefaultTests.cs: -------------------------------------------------------------------------------- 1 | using CSharpFunctionalExtensions.Tests.ResultTests; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions; 6 | 7 | public class GetValueOrDefaultTests : TestBase 8 | { 9 | 10 | [Fact] 11 | public void GetValueOrDefault_extracts_value_if_not_null() 12 | { 13 | Maybe maybe = T.Value; 14 | 15 | T myClass = maybe.GetValueOrDefault(); 16 | 17 | myClass.Should().Be(T.Value); 18 | } 19 | 20 | [Fact] 21 | public void GetValueOrDefault_extracts_null_if_no_value() 22 | { 23 | Maybe maybe = null; 24 | 25 | T myClass = maybe.GetValueOrDefault(); 26 | 27 | myClass.Should().BeNull(); 28 | } 29 | 30 | [Fact] 31 | public void Can_use_selector_in_GetValueOrDefault() 32 | { 33 | Maybe maybe = new MyClass { Property = "Some value" }; 34 | 35 | string value = maybe.GetValueOrDefault(x => x.Property); 36 | 37 | value.Should().Be("Some value"); 38 | } 39 | 40 | [Fact] 41 | public void Can_use_default_value_in_GetValueOrDefault() 42 | { 43 | Maybe maybe = null; 44 | 45 | string value = maybe.GetValueOrDefault(""); 46 | 47 | value.Should().Be(""); 48 | } 49 | 50 | private class MyClass 51 | { 52 | public string Property { get; set; } 53 | } 54 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/GetValueOrThrowTests.Task.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using FluentAssertions; 4 | using Xunit; 5 | 6 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 7 | { 8 | public class GetValueOrThrowTests_Task : MaybeTestBase 9 | { 10 | 11 | [Fact] 12 | public async Task GetValueOrThrow_Task_throws_with_message_if_source_is_empty() 13 | { 14 | const string errorMessage = "Maybe is none"; 15 | 16 | Func> func = () => Maybe.None.AsTask().GetValueOrThrow(errorMessage); 17 | 18 | await func.Should().ThrowAsync().WithMessage(errorMessage); 19 | } 20 | 21 | [Fact] 22 | public async Task GetValueOrThrow_Task_returns_value_if_source_has_value() 23 | { 24 | const int value = 1; 25 | var maybe = Maybe.From(value).AsTask(); 26 | 27 | const string errorMessage = "Maybe is none"; 28 | var result = await maybe.GetValueOrThrow(errorMessage); 29 | 30 | result.Should().Be(value); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/GetValueOrThrowTests.ValueTask.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using CSharpFunctionalExtensions.ValueTasks; 4 | using FluentAssertions; 5 | using Xunit; 6 | 7 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 8 | { 9 | public class GetValueOrThrowTests_ValueTask : MaybeTestBase 10 | { 11 | 12 | [Fact] 13 | public void Async_GetValueOrThrow_throws_with_message_if_source_is_empty() 14 | { 15 | const string errorMessage = "Maybe is none"; 16 | 17 | Func> func = async () => await Maybe.None.AsValueTask().GetValueOrThrow(errorMessage); 18 | 19 | func.Should().ThrowAsync().WithMessage(errorMessage); 20 | } 21 | 22 | [Fact] 23 | public async Task Async_GetValueOrThrow_returns_value_if_source_has_value() 24 | { 25 | const int value = 1; 26 | var maybe = Maybe.From(value).AsValueTask(); 27 | 28 | const string errorMessage = "Maybe is none"; 29 | var result = await maybe.GetValueOrThrow(errorMessage); 30 | 31 | result.Should().Be(value); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/MapTests.Task.Left.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 6 | { 7 | public class MapTests_Task_Left : MaybeTestBase 8 | { 9 | [Fact] 10 | public async Task Map_Task_Left_returns_mapped_value() 11 | { 12 | Maybe maybe = T.Value; 13 | 14 | var maybe2 = await maybe.AsTask().Map(ExpectAndReturn(T.Value, T.Value2)); 15 | 16 | maybe2.HasValue.Should().BeTrue(); 17 | maybe2.Value.Should().Be(T.Value2); 18 | } 19 | 20 | [Fact] 21 | public async Task Map_Task_Left_returns_no_value_if_initial_maybe_is_null() 22 | { 23 | Maybe maybe = null; 24 | 25 | var maybe2 = await maybe.AsTask().Map(ExpectAndReturn(null, T.Value2)); 26 | 27 | maybe2.HasValue.Should().BeFalse(); 28 | } 29 | 30 | [Fact] 31 | public async Task Map_Task_Left_provides_context_to_selector() 32 | { 33 | Maybe maybe = T.Value; 34 | var context = 5; 35 | 36 | var maybe2 = await maybe 37 | .AsTask() 38 | .Map( 39 | (value, ctx) => 40 | { 41 | ctx.Should().Be(context); 42 | return value; 43 | }, 44 | context 45 | ); 46 | 47 | maybe2.HasValue.Should().BeTrue(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/MapTests.Task.Right.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 6 | { 7 | public class MapTests_Task_Right : MaybeTestBase 8 | { 9 | [Fact] 10 | public async Task Map_Task_Right_returns_mapped_value() 11 | { 12 | Maybe maybe = T.Value; 13 | 14 | var maybe2 = await maybe.Map(ExpectAndReturn_Task(T.Value, T.Value2)); 15 | 16 | maybe2.HasValue.Should().BeTrue(); 17 | maybe2.Value.Should().Be(T.Value2); 18 | } 19 | 20 | [Fact] 21 | public async Task Map_Task_Right_returns_no_value_if_initial_maybe_is_null() 22 | { 23 | Maybe maybe = null; 24 | 25 | var maybe2 = await maybe.Map(ExpectAndReturn_Task(null, T.Value2)); 26 | 27 | maybe2.HasValue.Should().BeFalse(); 28 | } 29 | 30 | [Fact] 31 | public async Task Map_Task_Right_provides_context_to_selector() 32 | { 33 | Maybe maybe = T.Value; 34 | var context = 5; 35 | 36 | var maybe2 = await maybe.Map( 37 | (value, ctx) => 38 | { 39 | ctx.Should().Be(context); 40 | return value.AsTask(); 41 | }, 42 | context 43 | ); 44 | 45 | maybe2.HasValue.Should().BeTrue(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/MapTests.Task.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 6 | { 7 | public class MapTests_Task : MaybeTestBase 8 | { 9 | [Fact] 10 | public async Task Map_Task_returns_mapped_value() 11 | { 12 | Maybe maybe = T.Value; 13 | 14 | var maybe2 = await maybe.AsTask().Map(ExpectAndReturn_Task(T.Value, T.Value2)); 15 | 16 | maybe2.HasValue.Should().BeTrue(); 17 | maybe2.Value.Should().Be(T.Value2); 18 | } 19 | 20 | [Fact] 21 | public async Task Map_Task_returns_no_value_if_initial_maybe_is_null() 22 | { 23 | Maybe maybe = null; 24 | 25 | var maybe2 = await maybe.AsTask().Map(ExpectAndReturn_Task(null, T.Value2)); 26 | 27 | maybe2.HasValue.Should().BeFalse(); 28 | } 29 | 30 | [Fact] 31 | public async Task Map_Task_provides_context_to_selector() 32 | { 33 | Maybe maybe = T.Value; 34 | var context = 5; 35 | 36 | var maybe2 = await maybe 37 | .AsTask() 38 | .Map( 39 | (value, ctx) => 40 | { 41 | ctx.Should().Be(context); 42 | return value.AsTask(); 43 | }, 44 | context 45 | ); 46 | 47 | maybe2.HasValue.Should().BeTrue(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/MapTests.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using Xunit; 3 | 4 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 5 | { 6 | public class MapTests : MaybeTestBase 7 | { 8 | [Fact] 9 | public void Map_returns_mapped_value() 10 | { 11 | Maybe maybe = T.Value; 12 | 13 | var maybe2 = maybe.Map(ExpectAndReturn(T.Value, T.Value2)); 14 | 15 | maybe2.HasValue.Should().BeTrue(); 16 | maybe2.Value.Should().Be(T.Value2); 17 | } 18 | 19 | [Fact] 20 | public void Map_returns_no_value_if_initial_maybe_is_null() 21 | { 22 | Maybe maybe = null; 23 | 24 | var maybe2 = maybe.Map(ExpectAndReturn(null, T.Value2)); 25 | 26 | maybe2.HasValue.Should().BeFalse(); 27 | } 28 | 29 | [Fact] 30 | public void Map_provides_context_to_selector() 31 | { 32 | Maybe maybe = T.Value; 33 | var context = 5; 34 | 35 | var maybe2 = maybe.Map( 36 | (value, ctx) => 37 | { 38 | ctx.Should().Be(context); 39 | return value; 40 | }, 41 | context 42 | ); 43 | 44 | maybe2.HasValue.Should().BeTrue(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/OptionalTests.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using Xunit; 3 | 4 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions; 5 | 6 | public class OptionalTests 7 | { 8 | [Fact] 9 | public void Optional_AbsentResult_ShouldBeSuccessWithNoValue() 10 | { 11 | var absent = Maybe>.None.Optional(); 12 | 13 | absent.IsSuccess.Should().BeTrue(); 14 | absent.Value.HasNoValue.Should().BeTrue(); 15 | } 16 | 17 | [Fact] 18 | public void Optional_PresentFailedResult_ShouldBeFailureWithError() 19 | { 20 | var presentFailed = Maybe.From(Result.Failure("oops")).Optional(); 21 | 22 | presentFailed.IsFailure.Should().BeTrue(); 23 | presentFailed.Error.Should().Be("oops"); 24 | } 25 | 26 | [Fact] 27 | public void Optional_PresentSuccessResult_ShouldBeSuccessWithValue() 28 | { 29 | var presentSuccess = Maybe.From(Result.Success("yay")).Optional(); 30 | 31 | presentSuccess.IsSuccess.Should().BeTrue(); 32 | presentSuccess.Value.Value.Should().Be("yay"); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/OrTests.Task.Left.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 6 | { 7 | public class OrTests_Task_Left : MaybeTestBase 8 | { 9 | [Fact] 10 | public async Task Or_Task_Left_fallback_value_returns_source_if_source_has_value() 11 | { 12 | Maybe maybe = T.Value; 13 | 14 | var maybe2 = await maybe.AsTask().Or(T.Value2); 15 | 16 | maybe2.HasValue.Should().BeTrue(); 17 | maybe2.Should().Be(T.Value); 18 | } 19 | 20 | [Fact] 21 | public async Task Or_Task_Left_fallback_value_returns_a_new_instance_with_value_when_source_is_empty() 22 | { 23 | var maybeTask = Maybe.None; 24 | 25 | var maybe2 = await maybeTask.AsTask().Or(T.Value2); 26 | 27 | maybe2.HasValue.Should().BeTrue(); 28 | maybe2.Should().Be(T.Value2); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/OrTests.Task.Right.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 6 | { 7 | public class OrTests_Task_Right : MaybeTestBase 8 | { 9 | [Fact] 10 | public async Task Or_Task_Right_fallback_value_returns_source_if_source_has_value() 11 | { 12 | Maybe maybe = T.Value; 13 | 14 | var maybe2 = await maybe.Or(() => T.Value2.AsTask()); 15 | 16 | maybe2.HasValue.Should().BeTrue(); 17 | maybe2.Should().Be(T.Value); 18 | } 19 | 20 | [Fact] 21 | public async Task Or_Task_Right_fallback_value_returns_a_new_instance_with_value_when_source_is_empty() 22 | { 23 | var maybeTask = Maybe.None; 24 | 25 | var maybe2 = await maybeTask.Or(() => T.Value2.AsTask()); 26 | 27 | maybe2.HasValue.Should().BeTrue(); 28 | maybe2.Should().Be(T.Value2); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/OrTests.Task.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 6 | { 7 | public class OrTests_Task : MaybeTestBase 8 | { 9 | [Fact] 10 | public async Task Or_Task_fallback_value_returns_source_if_source_has_value() 11 | { 12 | Maybe maybe = T.Value; 13 | 14 | var maybe2 = await maybe.AsTask().Or(T.Value2.AsTask()); 15 | 16 | maybe2.HasValue.Should().BeTrue(); 17 | maybe2.Should().Be(T.Value); 18 | } 19 | 20 | [Fact] 21 | public async Task Or_Task_fallback_value_returns_a_new_instance_with_value_when_source_is_empty() 22 | { 23 | var maybeTask = Maybe.None; 24 | 25 | var maybe2 = await maybeTask.AsTask().Or(T.Value2.AsTask()); 26 | 27 | maybe2.HasValue.Should().BeTrue(); 28 | maybe2.Should().Be(T.Value2); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/OrTests.ValueTask.Left.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using CSharpFunctionalExtensions.ValueTasks; 3 | using FluentAssertions; 4 | using Xunit; 5 | 6 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 7 | { 8 | public class OrTests_ValueTask_Left : MaybeTestBase 9 | { 10 | [Fact] 11 | public async Task Or_ValueTask_Left_fallback_value_returns_source_if_source_has_value() 12 | { 13 | Maybe maybe = T.Value; 14 | 15 | var maybe2 = await maybe.AsValueTask().Or(T.Value2); 16 | 17 | maybe2.HasValue.Should().BeTrue(); 18 | maybe2.Should().Be(T.Value); 19 | } 20 | 21 | [Fact] 22 | public async Task Or_ValueTask_Left_fallback_value_returns_a_new_instance_with_value_when_source_is_empty() 23 | { 24 | var maybeValueTask = Maybe.None; 25 | 26 | var maybe2 = await maybeValueTask.AsValueTask().Or(T.Value2); 27 | 28 | maybe2.HasValue.Should().BeTrue(); 29 | maybe2.Should().Be(T.Value2); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/OrTests.ValueTask.Right.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using CSharpFunctionalExtensions.ValueTasks; 3 | using FluentAssertions; 4 | using Xunit; 5 | 6 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 7 | { 8 | public class OrTests_ValueTask_Right : MaybeTestBase 9 | { 10 | [Fact] 11 | public async Task Or_ValueTask_Right_fallback_value_returns_source_if_source_has_value() 12 | { 13 | Maybe maybe = T.Value; 14 | 15 | var maybe2 = await maybe.Or(() => T.Value2.AsValueTask()); 16 | 17 | maybe2.HasValue.Should().BeTrue(); 18 | maybe2.Should().Be(T.Value); 19 | } 20 | 21 | [Fact] 22 | public async Task Or_ValueTask_Right_fallback_value_returns_a_new_instance_with_value_when_source_is_empty() 23 | { 24 | var maybeValueTask = Maybe.None; 25 | 26 | var maybe2 = await maybeValueTask.Or(() => T.Value2.AsValueTask()); 27 | 28 | maybe2.HasValue.Should().BeTrue(); 29 | maybe2.Should().Be(T.Value2); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/OrTests.ValueTask.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using CSharpFunctionalExtensions.ValueTasks; 3 | using FluentAssertions; 4 | using Xunit; 5 | 6 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 7 | { 8 | public class OrTests_ValueTask : MaybeTestBase 9 | { 10 | [Fact] 11 | public async Task Or_ValueTask_fallback_value_returns_source_if_source_has_value() 12 | { 13 | Maybe maybe = T.Value; 14 | 15 | var maybe2 = await maybe.AsValueTask().Or(T.Value2.AsValueTask()); 16 | 17 | maybe2.HasValue.Should().BeTrue(); 18 | maybe2.Should().Be(T.Value); 19 | } 20 | 21 | [Fact] 22 | public async Task Or_ValueTask_fallback_value_returns_a_new_instance_with_value_when_source_is_empty() 23 | { 24 | var maybeValueTask = Maybe.None; 25 | 26 | var maybe2 = await maybeValueTask.AsValueTask().Or(T.Value2.AsValueTask()); 27 | 28 | maybe2.HasValue.Should().BeTrue(); 29 | maybe2.Should().Be(T.Value2); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/SelectTests.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using Xunit; 3 | 4 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions; 5 | 6 | public class SelectTests 7 | { 8 | [Fact] 9 | public void Select_returns_new_maybe() 10 | { 11 | Maybe maybe = new MyClass { Property = "Some value" }; 12 | 13 | Maybe maybe2 = maybe.Select(x => x.Property); 14 | 15 | maybe2.HasValue.Should().BeTrue(); 16 | maybe2.Value.Should().Be("Some value"); 17 | } 18 | 19 | [Fact] 20 | public void Select_returns_no_value_if_no_value_passed_in() 21 | { 22 | Maybe maybe = null; 23 | 24 | Maybe maybe2 = maybe.Select(x => x.Property); 25 | 26 | maybe2.HasValue.Should().BeFalse(); 27 | } 28 | 29 | private class MyClass 30 | { 31 | public string Property { get; set; } 32 | } 33 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/ToListTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using CSharpFunctionalExtensions.Tests.ResultTests; 3 | using FluentAssertions; 4 | using Xunit; 5 | 6 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions; 7 | 8 | public class ToListTest : TestBase 9 | { 10 | 11 | [Fact] 12 | public void ToList_gives_empty_list_if_null() 13 | { 14 | Maybe maybe = null; 15 | 16 | List myClasses = maybe.ToList(); 17 | 18 | myClasses.Count.Should().Be(0); 19 | } 20 | 21 | [Fact] 22 | public void ToList_gives_single_item_list_if_not_null() 23 | { 24 | Maybe maybe = T.Value; 25 | 26 | List myClasses = maybe.ToList(); 27 | 28 | myClasses.Count.Should().Be(1); 29 | myClasses[0].Should().Be(T.Value); 30 | } 31 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/TryFindTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions; 6 | 7 | public class TryFindTests 8 | { 9 | [Fact] 10 | public void TryFind_dict_does_not_contains_key() 11 | { 12 | var dict = new Dictionary(); 13 | 14 | var maybe = dict.TryFind("key"); 15 | 16 | maybe.HasValue.Should().BeFalse(); 17 | } 18 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/WhereTests.Task.Left.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 6 | { 7 | public class WhereTests_Task_Left : MaybeTestBase 8 | { 9 | [Fact] 10 | public async Task Where_Task_Left_returns_value_if_predicate_returns_true() 11 | { 12 | Maybe maybe = T.Value; 13 | 14 | var maybe2 = await maybe.AsTask().Where(ExpectAndReturn(T.Value, true)); 15 | 16 | maybe2.HasValue.Should().BeTrue(); 17 | maybe2.Value.Should().Be(T.Value); 18 | } 19 | 20 | [Fact] 21 | public async Task Where_Task_Left_returns_no_value_if_predicate_returns_false() 22 | { 23 | Maybe maybe = T.Value; 24 | 25 | var maybe2 = await maybe.AsTask().Where(ExpectAndReturn(T.Value, false)); 26 | 27 | maybe2.HasValue.Should().BeFalse(); 28 | } 29 | 30 | [Theory] 31 | [InlineData(true)] 32 | [InlineData(false)] 33 | public async Task Where_Task_Left_returns_no_value_if_initial_maybe_is_null(bool predicateResult) 34 | { 35 | Maybe maybe = null; 36 | 37 | var maybe2 = await maybe.AsTask().Where(ExpectAndReturn(null, predicateResult)); 38 | 39 | maybe2.HasValue.Should().BeFalse(); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/WhereTests.Task.Right.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 6 | { 7 | public class WhereTests_Task_Right : MaybeTestBase 8 | { 9 | [Fact] 10 | public async Task Where_Task_Right_returns_value_if_predicate_returns_true() 11 | { 12 | Maybe maybe = T.Value; 13 | 14 | var maybe2 = await maybe.Where(ExpectAndReturn_Task(T.Value, true)); 15 | 16 | maybe2.HasValue.Should().BeTrue(); 17 | maybe2.Value.Should().Be(T.Value); 18 | } 19 | 20 | [Fact] 21 | public async Task Where_Task_Right_returns_no_value_if_predicate_returns_false() 22 | { 23 | Maybe maybe = T.Value; 24 | 25 | var maybe2 = await maybe.Where(ExpectAndReturn_Task(T.Value, false)); 26 | 27 | maybe2.HasValue.Should().BeFalse(); 28 | } 29 | 30 | [Theory] 31 | [InlineData(true)] 32 | [InlineData(false)] 33 | public async Task Where_Task_Right_returns_no_value_if_initial_maybe_is_null(bool predicateResult) 34 | { 35 | Maybe maybe = null; 36 | 37 | var maybe2 = await maybe.Where(ExpectAndReturn_Task(null, predicateResult)); 38 | 39 | maybe2.HasValue.Should().BeFalse(); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/WhereTests.Task.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 6 | { 7 | public class WhereTests_Task : MaybeTestBase 8 | { 9 | [Fact] 10 | public async Task Where_Task_returns_value_if_predicate_returns_true() 11 | { 12 | Maybe maybe = T.Value; 13 | 14 | var maybe2 = await maybe.AsTask().Where(ExpectAndReturn_Task(T.Value, true)); 15 | 16 | maybe2.HasValue.Should().BeTrue(); 17 | maybe2.Value.Should().Be(T.Value); 18 | } 19 | 20 | [Fact] 21 | public async Task Where_Task_returns_no_value_if_predicate_returns_false() 22 | { 23 | Maybe maybe = T.Value; 24 | 25 | var maybe2 = await maybe.AsTask().Where(ExpectAndReturn_Task(T.Value, false)); 26 | 27 | maybe2.HasValue.Should().BeFalse(); 28 | } 29 | 30 | [Theory] 31 | [InlineData(true)] 32 | [InlineData(false)] 33 | public async Task Where_Task_returns_no_value_if_initial_maybe_is_null(bool predicateResult) 34 | { 35 | Maybe maybe = null; 36 | 37 | var maybe2 = await maybe.AsTask().Where(ExpectAndReturn_Task(null, predicateResult)); 38 | 39 | maybe2.HasValue.Should().BeFalse(); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/WhereTests.ValueTask.Left.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using CSharpFunctionalExtensions.ValueTasks; 3 | using FluentAssertions; 4 | using Xunit; 5 | 6 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 7 | { 8 | public class WhereTests_ValueTask_Left : MaybeTestBase 9 | { 10 | [Fact] 11 | public async ValueTask Where_ValueTask_Left_returns_value_if_predicate_returns_true() 12 | { 13 | Maybe maybe = T.Value; 14 | 15 | var maybe2 = await maybe.AsValueTask().Where(ExpectAndReturn(T.Value, true)); 16 | 17 | maybe2.HasValue.Should().BeTrue(); 18 | maybe2.Value.Should().Be(T.Value); 19 | } 20 | 21 | [Fact] 22 | public async ValueTask Where_ValueTask_Left_returns_no_value_if_predicate_returns_false() 23 | { 24 | Maybe maybe = T.Value; 25 | 26 | var maybe2 = await maybe.AsValueTask().Where(ExpectAndReturn(T.Value, false)); 27 | 28 | maybe2.HasValue.Should().BeFalse(); 29 | } 30 | 31 | [Theory] 32 | [InlineData(true)] 33 | [InlineData(false)] 34 | public async ValueTask Where_ValueTask_Left_returns_no_value_if_initial_maybe_is_null(bool predicateResult) 35 | { 36 | Maybe maybe = null; 37 | 38 | var maybe2 = await maybe.AsValueTask().Where(ExpectAndReturn(null, predicateResult)); 39 | 40 | maybe2.HasValue.Should().BeFalse(); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/WhereTests.ValueTask.Right.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using CSharpFunctionalExtensions.ValueTasks; 3 | using FluentAssertions; 4 | using Xunit; 5 | 6 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 7 | { 8 | public class WhereTests_ValueTask_Right : MaybeTestBase 9 | { 10 | [Fact] 11 | public async ValueTask Where_ValueTask_Right_returns_value_if_predicate_returns_true() 12 | { 13 | Maybe maybe = T.Value; 14 | 15 | var maybe2 = await maybe.Where(ExpectAndReturn_ValueTask(T.Value, true)); 16 | 17 | maybe2.HasValue.Should().BeTrue(); 18 | maybe2.Value.Should().Be(T.Value); 19 | } 20 | 21 | [Fact] 22 | public async ValueTask Where_ValueTask_Right_returns_no_value_if_predicate_returns_false() 23 | { 24 | Maybe maybe = T.Value; 25 | 26 | var maybe2 = await maybe.Where(ExpectAndReturn_ValueTask(T.Value, false)); 27 | 28 | maybe2.HasValue.Should().BeFalse(); 29 | } 30 | 31 | [Theory] 32 | [InlineData(true)] 33 | [InlineData(false)] 34 | public async ValueTask Where_ValueTask_Right_returns_no_value_if_initial_maybe_is_null(bool predicateResult) 35 | { 36 | Maybe maybe = null; 37 | 38 | var maybe2 = await maybe.Where(ExpectAndReturn_ValueTask(null, predicateResult)); 39 | 40 | maybe2.HasValue.Should().BeFalse(); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/WhereTests.ValueTask.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using CSharpFunctionalExtensions.ValueTasks; 3 | using FluentAssertions; 4 | using Xunit; 5 | 6 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 7 | { 8 | public class WhereTests_ValueTask : MaybeTestBase 9 | { 10 | [Fact] 11 | public async ValueTask Where_ValueTask_returns_value_if_predicate_returns_true() 12 | { 13 | Maybe maybe = T.Value; 14 | 15 | var maybe2 = await maybe.AsValueTask().Where(ExpectAndReturn_ValueTask(T.Value, true)); 16 | 17 | maybe2.HasValue.Should().BeTrue(); 18 | maybe2.Value.Should().Be(T.Value); 19 | } 20 | 21 | [Fact] 22 | public async ValueTask Where_ValueTask_returns_no_value_if_predicate_returns_false() 23 | { 24 | Maybe maybe = T.Value; 25 | 26 | var maybe2 = await maybe.AsValueTask().Where(ExpectAndReturn_ValueTask(T.Value, false)); 27 | 28 | maybe2.HasValue.Should().BeFalse(); 29 | } 30 | 31 | [Theory] 32 | [InlineData(true)] 33 | [InlineData(false)] 34 | public async ValueTask Where_ValueTask_returns_no_value_if_initial_maybe_is_null(bool predicateResult) 35 | { 36 | Maybe maybe = null; 37 | 38 | var maybe2 = await maybe.AsValueTask().Where(ExpectAndReturn_ValueTask(null, predicateResult)); 39 | 40 | maybe2.HasValue.Should().BeFalse(); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/WhereTests.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using Xunit; 3 | 4 | namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions 5 | { 6 | public class WhereTests : MaybeTestBase 7 | { 8 | [Fact] 9 | public void Where_returns_value_if_predicate_returns_true() 10 | { 11 | Maybe maybe = T.Value; 12 | 13 | var maybe2 = maybe.Where(ExpectAndReturn(T.Value, true)); 14 | 15 | maybe2.HasValue.Should().BeTrue(); 16 | maybe2.Value.Should().Be(T.Value); 17 | } 18 | 19 | [Fact] 20 | public void Where_returns_no_value_if_predicate_returns_false() 21 | { 22 | Maybe maybe = T.Value; 23 | 24 | var maybe2 = maybe.Where(ExpectAndReturn(T.Value, false)); 25 | 26 | maybe2.HasValue.Should().BeFalse(); 27 | } 28 | 29 | [Theory] 30 | [InlineData(true)] 31 | [InlineData(false)] 32 | public void Where_returns_no_value_if_initial_maybe_is_null(bool predicateResult) 33 | { 34 | Maybe maybe = null; 35 | 36 | var maybe2 = maybe.Where(ExpectAndReturn(null, predicateResult)); 37 | 38 | maybe2.HasValue.Should().BeFalse(); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/MaybeTests/ImplicitConversionTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using FluentAssertions; 4 | using Xunit; 5 | 6 | namespace CSharpFunctionalExtensions.Tests.MaybeTests 7 | { 8 | public class ImplicitConversionTests 9 | { 10 | [Fact] 11 | public void Implicit_conversion_of_reference_type() 12 | { 13 | StringVO stringVo = default; 14 | 15 | // ReSharper disable once ExpressionIsAlwaysNull 16 | string stringPrimitive = stringVo; 17 | 18 | stringPrimitive.Should().BeNull(); 19 | } 20 | 21 | [Fact] 22 | public void Implicit_conversion_of_value_type() 23 | { 24 | IntVO intVo = default; 25 | 26 | // ReSharper disable once ExpressionIsAlwaysNull 27 | int intPrimitive = intVo; 28 | 29 | intPrimitive.Should().Be(0); 30 | } 31 | 32 | public class StringVO : SimpleValueObject 33 | { 34 | public StringVO(string value) 35 | : base(value) 36 | { 37 | } 38 | 39 | protected override IEnumerable GetComparableEqualityComponents() 40 | { 41 | yield return Value.ToLower(); 42 | } 43 | } 44 | 45 | public class IntVO : SimpleValueObject 46 | { 47 | public IntVO(int value) 48 | : base(value) 49 | { 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/NonParallelTestCollectionAttribute.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace CSharpFunctionalExtensions.Tests 4 | { 5 | [CollectionDefinition(Name, DisableParallelization = true)] 6 | public sealed class NonParallelTestCollectionDefinition 7 | { 8 | internal const string Name = "Non-Parallel Collection"; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/ResultTests/AmbiguityTests.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Xunit; 3 | 4 | namespace CSharpFunctionalExtensions.Tests.ResultTests; 5 | 6 | public class AmbiguityTests 7 | { 8 | [Fact] 9 | public void The_following_method_calls_should_compile_without_raising_ambiguity_errors() 10 | { 11 | GetProfileAsync(); 12 | GetProfileWithErrorAsync(); 13 | } 14 | 15 | [Fact] 16 | public async Task The_following_code_should_compile_without_raising_ambiguity_errors() 17 | { 18 | Result result = Result.Success(new()); 19 | 20 | Task> GetTask() => Task.FromResult(Result.Success(new())); 21 | 22 | await result 23 | .Bind(async _ => await GetTask()); 24 | } 25 | 26 | private Task> GetProfileAsync() => 27 | Result.Try(async () => 28 | { 29 | await Task.Yield(); 30 | 31 | return new Profile(); 32 | }); 33 | 34 | private Task> GetProfileWithErrorAsync() => 35 | Result.Try(async () => 36 | { 37 | await Task.Yield(); 38 | 39 | return new Profile(); 40 | }, _ => new Error()); 41 | 42 | private class Profile 43 | { 44 | } 45 | 46 | private class Error 47 | { 48 | } 49 | 50 | class T1 51 | { 52 | } 53 | 54 | class T2 55 | { 56 | } 57 | 58 | class E 59 | { 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/ResultTests/Extensions/AsMaybeTests.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | using FluentAssertions; 3 | 4 | namespace CSharpFunctionalExtensions.Tests.ResultTests.Extensions; 5 | 6 | public class AsMaybeTests : TestBase 7 | { 8 | [Fact] 9 | public void Error_returns_None() 10 | { 11 | var result = Result.Failure(ErrorMessage); 12 | result.AsMaybe().HasValue.Should().BeFalse(); 13 | } 14 | 15 | [Fact] 16 | public void Success_returns_Some() 17 | { 18 | var result = Result.Success(T.Value); 19 | var asMaybe = result.AsMaybe(); 20 | 21 | asMaybe.HasValue.Should().BeTrue(); 22 | asMaybe.Value.Should().Be(T.Value); 23 | } 24 | 25 | [Fact] 26 | public void Null_value_returns_None() 27 | { 28 | var result = Result.Success(null); 29 | var asMaybe = result.AsMaybe(); 30 | 31 | asMaybe.HasValue.Should().BeFalse(); 32 | } 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/ResultTests/Extensions/BindZipTests.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using FluentAssertions; 3 | using FluentAssertions.Execution; 4 | using Xunit; 5 | 6 | namespace CSharpFunctionalExtensions.Tests.ResultTests.Extensions; 7 | 8 | public class BindZipTests : BindTestsBase 9 | { 10 | [Fact] 11 | public void BindZip_T_with_Bind_K_returns_success() 12 | { 13 | Result<(T, K)> output = Success_T(T.Value).BindZip(_ => Success_K()); 14 | 15 | using (var _ = new AssertionScope()) 16 | { 17 | AssertSuccess(output); 18 | 19 | (var _, var _, (T t, K k)) = output; 20 | t.Should().Be(T.Value); 21 | k.Should().Be(K.Value); 22 | } 23 | } 24 | 25 | [Fact] 26 | public void BindZip_T_With_Bind_K_eight_times_returns_success() 27 | { 28 | Result<(T, K, K, K, K, K, K, K)> output = Success_T(T.Value) 29 | .BindZip(_ => Success_K()) 30 | .BindZip((_, _) => Success_K()) 31 | .BindZip((_, _, _) => Success_K()) 32 | .BindZip((_, _, _, _) => Success_K()) 33 | .BindZip((_, _, _, _, _) => Success_K()) 34 | .BindZip((_, _, _, _, _, _) => Success_K()) 35 | .BindZip((_, _, _, _, _, _, _) => Success_K()); 36 | 37 | ((ITuple)output.Value).Length.Should().Be(8); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/ResultTests/Extensions/EnsureNotNullTests.Base.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions.Tests.ResultTests.Extensions; 5 | 6 | public class EnsureNotNullTests_Base : TestBase 7 | { 8 | protected bool factoryExecuted; 9 | 10 | protected Func GetErrorFactory(E e) 11 | { 12 | return () => 13 | { 14 | factoryExecuted = true; 15 | 16 | return e; 17 | }; 18 | } 19 | 20 | protected Func> GetTaskErrorFactory(E e) => GetErrorFactory(Task.FromResult(e)); 21 | 22 | protected Func> GetValueTaskErrorFactory(E e) => GetErrorFactory(ValueTask.FromResult(e)); 23 | 24 | protected struct V 25 | { 26 | public static readonly V Value = new V(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/ResultTests/Extensions/GetValueOrDefaultTests.cs: -------------------------------------------------------------------------------- 1 | using CSharpFunctionalExtensions.Tests.ResultTests; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace CSharpFunctionalExtensions.Tests.ResultTests.Extensions; 6 | 7 | public class GetValueOrDefaultTests : TestBase 8 | { 9 | 10 | [Fact] 11 | public void GetValueOrDefault_extracts_value_if_success() 12 | { 13 | Result result = T.Value; 14 | 15 | T myClass = result.GetValueOrDefault(); 16 | 17 | myClass.Should().Be(T.Value); 18 | } 19 | 20 | [Fact] 21 | public void GetValueOrDefault_extracts_null_if_failure() 22 | { 23 | Result result = Result.Failure(ErrorMessage); 24 | 25 | T myClass = result.GetValueOrDefault(); 26 | 27 | myClass.Should().BeNull(); 28 | } 29 | 30 | [Fact] 31 | public void Can_use_selector_in_GetValueOrDefault() 32 | { 33 | Result result = new MyClass { Property = "Some value" }; 34 | 35 | string value = result.GetValueOrDefault(x => x.Property); 36 | 37 | value.Should().Be("Some value"); 38 | } 39 | 40 | [Fact] 41 | public void Can_use_default_value_in_GetValueOrDefault() 42 | { 43 | Result result = Result.Failure(ErrorMessage); 44 | 45 | string value = result.GetValueOrDefault(""); 46 | 47 | value.Should().Be(""); 48 | } 49 | 50 | private class MyClass 51 | { 52 | public string Property { get; set; } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/ResultTests/Extensions/MapTests.Base.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace CSharpFunctionalExtensions.Tests.ResultTests.Extensions 4 | { 5 | public abstract class MapTestsBase : TestBase 6 | { 7 | protected bool FuncExecuted; 8 | 9 | protected MapTestsBase() 10 | { 11 | FuncExecuted = false; 12 | } 13 | 14 | protected K Func_K() 15 | { 16 | FuncExecuted = true; 17 | return K.Value; 18 | } 19 | 20 | protected K Func_T_K(T value) 21 | { 22 | FuncExecuted = true; 23 | return K.Value; 24 | } 25 | 26 | protected Task Task_Func_K() => Func_K().AsTask(); 27 | 28 | protected Task Task_Func_T_K(T value) => Func_T_K(value).AsTask(); 29 | 30 | protected ValueTask ValueTask_Func_K() => Func_K().AsValueTask(); 31 | 32 | protected ValueTask ValueTask_Func_T_K(T value) => Func_T_K(value).AsValueTask(); 33 | 34 | protected readonly string ContextMessage = "Context data"; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/ResultTests/Extensions/TapTests.Base.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace CSharpFunctionalExtensions.Tests.ResultTests.Extensions 4 | { 5 | public abstract class TapTestsBase : TestBase 6 | { 7 | protected bool actionExecuted; 8 | 9 | protected TapTestsBase() 10 | { 11 | actionExecuted = false; 12 | } 13 | 14 | protected void Action() 15 | { 16 | actionExecuted = true; 17 | } 18 | 19 | protected void Action_T(T _) 20 | { 21 | actionExecuted = true; 22 | } 23 | 24 | protected Task Task_Action() 25 | { 26 | actionExecuted = true; 27 | return Task.CompletedTask; 28 | } 29 | 30 | protected Task Task_Action_T(T _) 31 | { 32 | actionExecuted = true; 33 | return Task.CompletedTask; 34 | } 35 | 36 | protected ValueTask ValueTask_Action() 37 | { 38 | actionExecuted = true; 39 | return ValueTask.CompletedTask; 40 | } 41 | 42 | protected ValueTask ValueTask_Action_T(T _) 43 | { 44 | actionExecuted = true; 45 | return ValueTask.CompletedTask; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/ResultTests/Methods/FirstFailureOrSuccessTests.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using Xunit; 3 | 4 | namespace CSharpFunctionalExtensions.Tests.ResultTests.Methods 5 | { 6 | public class FirstFailureOrSuccessTests 7 | { 8 | [Fact] 9 | public void FirstFailureOrSuccess_returns_the_first_failed_result() 10 | { 11 | Result result1 = Result.Success(); 12 | Result result2 = Result.Failure("Failure 1"); 13 | Result result3 = Result.Failure("Failure 2"); 14 | 15 | Result result = Result.FirstFailureOrSuccess(result1, result2, result3); 16 | 17 | result.IsFailure.Should().BeTrue(); 18 | result.Error.Should().Be("Failure 1"); 19 | result.Should().Be(result2); 20 | } 21 | 22 | [Fact] 23 | public void FirstFailureOrSuccess_returns_success_if_no_failures() 24 | { 25 | Result result1 = Result.Success(); 26 | Result result2 = Result.Success(); 27 | Result result3 = Result.Success(); 28 | 29 | Result result = Result.FirstFailureOrSuccess(result1, result2, result3); 30 | 31 | result.IsSuccess.Should().BeTrue(); 32 | result.Should().Be(Result.Success()); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/ResultTests/Methods/TryTest.Base.Common.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions.Tests.ResultTests.Methods.Try 4 | { 5 | public abstract class TryTestBaseCommon : TestBase 6 | { 7 | protected TryTestBaseCommon() 8 | { 9 | FuncExecuted = false; 10 | } 11 | 12 | protected static readonly Exception Exception = new Exception(ErrorMessage); 13 | protected const string ErrorHandlerMessage = "Error message from error handler"; 14 | protected static readonly Func ErrorHandler = exc => ErrorHandlerMessage; 15 | protected static readonly Func ErrorHandler_E = exc => E.Value; 16 | 17 | protected bool FuncExecuted; 18 | } 19 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/ResultTests/Methods/TryTest.Base.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpFunctionalExtensions.Tests.ResultTests.Methods.Try 2 | { 3 | public abstract class TryTestBase : TryTestBaseCommon 4 | { 5 | protected void Action() => FuncExecuted = true; 6 | protected void Action_T(T _) => FuncExecuted = true; 7 | 8 | protected T Func_T() 9 | { 10 | FuncExecuted = true; 11 | return T.Value; 12 | } 13 | 14 | protected K Func_T_K(T _) 15 | { 16 | FuncExecuted = true; 17 | return K.Value; 18 | } 19 | 20 | protected T Throwing_Func_T() => throw Exception; 21 | protected K Throwing_Func_T_K(T _) => throw Exception; 22 | protected void Throwing_Action() => throw Exception; 23 | protected void Throwing_Action_T(T _) => throw Exception; 24 | 25 | } 26 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/ResultTests/Methods/TryValueTaskTest.Base.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace CSharpFunctionalExtensions.Tests.ResultTests.Methods.Try 4 | { 5 | public abstract class TryTestBaseValueTask : TryTestBaseCommon 6 | { 7 | protected ValueTask Func_ValueTask() 8 | { 9 | FuncExecuted = true; 10 | return ValueTask.CompletedTask; 11 | } 12 | 13 | protected ValueTask Func_T_ValueTask(T _) 14 | { 15 | FuncExecuted = true; 16 | return ValueTask.CompletedTask; 17 | } 18 | 19 | protected ValueTask Func_ValueTask_T() 20 | { 21 | FuncExecuted = true; 22 | return T.Value.AsValueTask(); 23 | } 24 | 25 | protected ValueTask Func_T_ValueTask_K(T _) 26 | { 27 | FuncExecuted = true; 28 | return K.Value.AsValueTask(); 29 | } 30 | 31 | protected ValueTask Throwing_Func_ValueTask() => Exception.AsValueTask(); 32 | protected ValueTask Throwing_Func_ValueTask_T() => Exception.AsValueTask(); 33 | protected ValueTask Throwing_Func_T_ValueTask(T _) => Exception.AsValueTask(); 34 | protected ValueTask Throwing_Func_T_ValueTask_K(T _) => Exception.AsValueTask(); 35 | 36 | } 37 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/TaskExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions.Tests 5 | { 6 | internal static class TaskExtensions 7 | { 8 | public static Task AsTask(this T obj) => Task.FromResult(obj); 9 | public static Task AsTask(this Exception exception) => Task.FromException(exception); 10 | public static Task AsTask(this Exception exception) => Task.FromException(exception); 11 | } 12 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/ValueObjectTests/AnotherTestEnumValueObject.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpFunctionalExtensions.Tests.ValueObjectTests 2 | { 3 | public sealed class AnotherTestEnumValueObject : EnumValueObject 4 | { 5 | public static readonly AnotherTestEnumValueObject One = new AnotherTestEnumValueObject(1, "name"); 6 | 7 | public static readonly AnotherTestEnumValueObject Two = new AnotherTestEnumValueObject(2, "test"); 8 | 9 | private AnotherTestEnumValueObject(long id, string name) : base(id, name) 10 | { 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/ValueObjectTests/TestEnumValueObject.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpFunctionalExtensions.Tests.ValueObjectTests 2 | { 3 | public sealed class TestEnumValueObject : EnumValueObject 4 | { 5 | public static readonly TestEnumValueObject One = new TestEnumValueObject(nameof(One)); 6 | 7 | public static readonly TestEnumValueObject Two = new TestEnumValueObject(nameof(Two)); 8 | 9 | public TestEnumValueObject(string key) : base(key) 10 | { 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions.Tests/ValueTaskExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using CSharpFunctionalExtensions.ValueTasks; 4 | 5 | namespace CSharpFunctionalExtensions.Tests 6 | { 7 | internal static class ValueTaskExtensions 8 | { 9 | public static ValueTask AsValueTask(this T obj) => obj.AsCompletedValueTask(); 10 | public static ValueTask AsValueTask(this Exception exception) => ValueTask.FromException(exception); 11 | public static ValueTask AsValueTask(this Exception exception) => ValueTask.FromException(exception); 12 | } 13 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/ICombine.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpFunctionalExtensions 2 | { 3 | public interface ICombine 4 | { 5 | ICombine Combine(ICombine value); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/AsMaybe.Task.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | // ReSharper disable ConvertNullableToShortForm 9 | /// 10 | /// Converts the struct to a . 11 | /// 12 | /// Returns the equivalent to the . 13 | public static async Task> AsMaybe(this Task> nullableTask) 14 | where T : struct 15 | { 16 | var nullable = await nullableTask.DefaultAwait(); 17 | return nullable.AsMaybe(); 18 | } 19 | 20 | #nullable enable 21 | /// 22 | /// Wraps the class instance in a . 23 | /// 24 | /// Returns if the class instance is null, otherwise returns . 25 | public static async Task> AsMaybe(this Task nullableTask) 26 | where T : class 27 | { 28 | var nullable = await nullableTask.DefaultAwait(); 29 | return nullable.AsMaybe(); 30 | } 31 | #nullable restore 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/AsMaybe.ValueTask.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | // ReSharper disable ConvertNullableToShortForm 10 | /// 11 | /// Converts the struct to a . 12 | /// 13 | /// Returns the equivalent to the . 14 | public static async ValueTask> AsMaybe(this ValueTask> nullableTask) 15 | where T : struct 16 | { 17 | var nullable = await nullableTask; 18 | return nullable.AsMaybe(); 19 | } 20 | 21 | #nullable enable 22 | /// 23 | /// Wraps the class instance in a . 24 | /// 25 | /// Returns if the class instance is null, otherwise returns . 26 | public static async ValueTask> AsMaybe(this ValueTask nullableTask) 27 | where T : class 28 | { 29 | var nullable = await nullableTask; 30 | return nullable.AsMaybe(); 31 | } 32 | #nullable restore 33 | } 34 | } 35 | #endif 36 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/AsNullable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class MaybeExtensions 6 | { 7 | // ReSharper disable ConvertNullableToShortForm 8 | /// 9 | /// Converts the to a struct. 10 | /// 11 | /// Returns the equivalent to the . 12 | #if NET5_0_OR_GREATER 13 | public static Nullable AsNullable(ref this Maybe value) 14 | where T : struct 15 | { 16 | return System.Runtime.CompilerServices.Unsafe.As, Nullable>(ref value); 17 | } 18 | #else 19 | public static Nullable AsNullable(in this Maybe value) 20 | where T : struct 21 | { 22 | // Should use `return Unsafe.AsRef<(ref value);` 23 | if (value.TryGetValue(out var result)) 24 | { 25 | return result; 26 | } 27 | return default; 28 | } 29 | #endif 30 | // ReSharper restore ConvertNullableToShortForm 31 | } 32 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Bind.Task.Left.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | public static async Task> Bind(this Task> maybeTask, Func> selector) 9 | { 10 | var maybe = await maybeTask.DefaultAwait(); 11 | return maybe.Bind(selector); 12 | } 13 | 14 | public static async Task> Bind(this Task> maybeTask, Func> selector, TContext context) 15 | { 16 | var maybe = await maybeTask.DefaultAwait(); 17 | return maybe.Bind(selector, context); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Bind.Task.Right.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | public static Task> Bind(this Maybe maybe, Func>> selector) 9 | { 10 | if (maybe.HasNoValue) 11 | return Maybe.None.AsCompletedTask(); 12 | 13 | return selector(maybe.GetValueOrThrow()); 14 | } 15 | 16 | public static Task> Bind( 17 | this Maybe maybe, 18 | Func>> selector, 19 | TContext context) 20 | { 21 | if (maybe.HasNoValue) 22 | return Maybe.None.AsCompletedTask(); 23 | 24 | return selector(maybe.GetValueOrThrow(), context); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Bind.Task.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | public static async Task> Bind(this Task> maybeTask, Func>> selector) 9 | { 10 | var maybe = await maybeTask.DefaultAwait(); 11 | return await maybe.Bind(selector).DefaultAwait(); 12 | } 13 | 14 | public static async Task> Bind(this Task> maybeTask, Func>> selector, TContext context) 15 | { 16 | var maybe = await maybeTask.DefaultAwait(); 17 | return await maybe.Bind(selector, context).DefaultAwait(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Bind.ValueTask.Left.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | public static async ValueTask> Bind(this ValueTask> maybeTask, Func> selector) 10 | { 11 | Maybe maybe = await maybeTask; 12 | return maybe.Bind(selector); 13 | } 14 | 15 | public static async ValueTask> Bind( 16 | this ValueTask> maybeTask, 17 | Func> selector, 18 | TContext context) 19 | { 20 | Maybe maybe = await maybeTask; 21 | return maybe.Bind(selector, context); 22 | } 23 | } 24 | } 25 | #endif 26 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Bind.ValueTask.Right.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | public static ValueTask> Bind(this Maybe maybe, Func>> selector) 10 | { 11 | if (maybe.HasNoValue) 12 | return Maybe.None.AsCompletedValueTask(); 13 | 14 | return selector(maybe.GetValueOrThrow()); 15 | } 16 | 17 | public static ValueTask> Bind( 18 | this Maybe maybe, 19 | Func>> selector, 20 | TContext context) 21 | { 22 | if (maybe.HasNoValue) 23 | return Maybe.None.AsCompletedValueTask(); 24 | 25 | return selector(maybe.GetValueOrThrow(), context); 26 | } 27 | } 28 | } 29 | #endif 30 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Bind.ValueTask.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | public static async ValueTask> Bind(this ValueTask> maybeTask, Func>> selector) 10 | { 11 | Maybe maybe = await maybeTask; 12 | return await maybe.Bind(selector); 13 | } 14 | 15 | public static async ValueTask> Bind( 16 | this ValueTask> maybeTask, 17 | Func>> selector, 18 | TContext context) 19 | { 20 | Maybe maybe = await maybeTask; 21 | return await maybe.Bind(selector, context); 22 | } 23 | } 24 | } 25 | #endif 26 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Bind.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class MaybeExtensions 6 | { 7 | public static Maybe Bind(in this Maybe maybe, Func> selector) 8 | { 9 | if (maybe.HasNoValue) 10 | return Maybe.None; 11 | 12 | return selector(maybe.GetValueOrThrow()); 13 | } 14 | 15 | public static Maybe Bind( 16 | in this Maybe maybe, 17 | Func> selector, 18 | TContext context 19 | ) 20 | { 21 | if (maybe.HasNoValue) 22 | return Maybe.None; 23 | 24 | return selector(maybe.GetValueOrThrow(), context); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/BindOptional.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class MaybeExtensions 6 | { 7 | /// 8 | /// Convert an optional value into a Result. The result, being optional, is of type Maybe. 9 | /// 10 | public static Result, TError> BindOptional( 11 | this Maybe maybe, 12 | Func> bind) 13 | { 14 | return maybe.Bind(v => Maybe.From(bind(v))).Optional(); 15 | } 16 | 17 | /// 18 | /// Convert an optional value into a Result. The result, being optional, is of type Maybe. 19 | /// 20 | public static Result> BindOptional( 21 | this Maybe maybe, 22 | Func> bind) 23 | { 24 | return maybe.Bind(v => Maybe.From(bind(v))).Optional(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Choose.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | public static IEnumerable Choose(this IEnumerable> source, Func selector) 9 | { 10 | using (var enumerator = source.GetEnumerator()) 11 | { 12 | while (enumerator.MoveNext()) 13 | { 14 | var item = enumerator.Current; 15 | if (item.HasValue) yield return selector(item.GetValueOrThrow()); 16 | } 17 | } 18 | } 19 | 20 | public static IEnumerable Choose(this IEnumerable> source) 21 | { 22 | using (var enumerator = source.GetEnumerator()) 23 | { 24 | while (enumerator.MoveNext()) 25 | { 26 | var item = enumerator.Current; 27 | if (item.HasValue) yield return item.GetValueOrThrow(); 28 | } 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Deconstruct.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpFunctionalExtensions 2 | { 3 | public static partial class MaybeExtensions 4 | { 5 | public static void Deconstruct(in this Maybe result, out bool hasValue, out T value) 6 | { 7 | hasValue = result.HasValue; 8 | value = result.GetValueOrDefault(); 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Execute.Task.Left.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | /// 9 | /// Executes the given if the produces a value 10 | /// 11 | /// 12 | /// 13 | /// 14 | /// 15 | public static async Task Execute(this Task> maybeTask, Action action) 16 | { 17 | var maybe = await maybeTask.DefaultAwait(); 18 | 19 | if (maybe.HasNoValue) 20 | return; 21 | 22 | action(maybe.GetValueOrThrow()); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Execute.Task.Right.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | /// 9 | /// Executes the given async if the has a value 10 | /// 11 | /// 12 | /// 13 | /// 14 | public static async Task Execute(this Maybe maybe, Func action) 15 | { 16 | if (maybe.HasNoValue) 17 | return; 18 | 19 | await action(maybe.GetValueOrThrow()).DefaultAwait(); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Execute.Task.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | /// 9 | /// Executes the given if the produces a value 10 | /// 11 | /// 12 | /// 13 | /// 14 | /// 15 | public static async Task Execute(this Task> maybeTask, Func asyncAction) 16 | { 17 | var maybe = await maybeTask.DefaultAwait(); 18 | 19 | if (maybe.HasNoValue) 20 | return; 21 | 22 | await asyncAction(maybe.GetValueOrThrow()).DefaultAwait(); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Execute.ValueTask.Left.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | /// 10 | /// Executes the given if the produces a value 11 | /// 12 | /// 13 | /// 14 | /// 15 | /// 16 | public static async Task Execute(this ValueTask> maybeTask, Action action) 17 | { 18 | var maybe = await maybeTask; 19 | 20 | if (maybe.HasNoValue) 21 | return; 22 | 23 | action(maybe.GetValueOrThrow()); 24 | } 25 | } 26 | } 27 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Execute.ValueTask.Right.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | /// 10 | /// Executes the given async if the has a value 11 | /// 12 | /// 13 | /// 14 | /// 15 | public static async Task Execute(this Maybe maybe, Func valueTask) 16 | { 17 | if (maybe.HasNoValue) 18 | return; 19 | 20 | await valueTask(maybe.GetValueOrThrow()); 21 | } 22 | } 23 | } 24 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Execute.ValueTask.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | /// 10 | /// Executes the given if the produces a value 11 | /// 12 | /// 13 | /// 14 | /// 15 | /// 16 | public static async Task Execute(this ValueTask> maybeTask, Func valueTask) 17 | { 18 | var maybe = await maybeTask; 19 | 20 | if (maybe.HasNoValue) 21 | return; 22 | 23 | await valueTask(maybe.GetValueOrThrow()); 24 | } 25 | } 26 | } 27 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Execute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class MaybeExtensions 6 | { 7 | /// 8 | /// Executes the given if the has a value 9 | /// 10 | /// 11 | /// 12 | /// 13 | public static void Execute(in this Maybe maybe, Action action) 14 | { 15 | if (maybe.HasNoValue) 16 | return; 17 | 18 | action(maybe.GetValueOrThrow()); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/ExecuteNoValue.Task.Left.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | /// 9 | /// Executes the given if the produces no value 10 | /// 11 | /// 12 | /// 13 | /// 14 | public static async Task ExecuteNoValue(this Task> maybeTask, Action action) 15 | { 16 | var maybe = await maybeTask.DefaultAwait(); 17 | 18 | if (maybe.HasValue) 19 | return; 20 | 21 | action(); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/ExecuteNoValue.Task.Right.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | /// 9 | /// Executes the given async if the has no value 10 | /// 11 | /// 12 | /// 13 | /// 14 | public static async Task ExecuteNoValue(this Maybe maybe, Func action) 15 | { 16 | if (maybe.HasValue) 17 | return; 18 | 19 | await action().DefaultAwait(); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/ExecuteNoValue.Task.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | /// 9 | /// Executes the given if the produces no value 10 | /// 11 | /// 12 | /// 13 | /// 14 | public static async Task ExecuteNoValue(this Task> maybeTask, Func asyncAction) 15 | { 16 | var maybe = await maybeTask.DefaultAwait(); 17 | 18 | if (maybe.HasValue) 19 | return; 20 | 21 | await asyncAction().DefaultAwait(); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/ExecuteNoValue.ValueTask.Left.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | /// 10 | /// Executes the given if the produces no value 11 | /// 12 | /// 13 | /// 14 | /// 15 | public static async Task ExecuteNoValue(this ValueTask> maybeTask, Action action) 16 | { 17 | var maybe = await maybeTask; 18 | 19 | if (maybe.HasValue) 20 | return; 21 | 22 | action(); 23 | } 24 | } 25 | } 26 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/ExecuteNoValue.ValueTask.Right.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | /// 10 | /// Executes the given async if the has no value 11 | /// 12 | /// 13 | /// 14 | /// 15 | public static async Task ExecuteNoValue(this Maybe maybe, Func valueTask) 16 | { 17 | if (maybe.HasValue) 18 | return; 19 | 20 | await valueTask(); 21 | } 22 | } 23 | } 24 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/ExecuteNoValue.ValueTask.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | /// 10 | /// Executes the given if the produces no value 11 | /// 12 | /// 13 | /// 14 | /// 15 | public static async Task ExecuteNoValue(this ValueTask> maybeTask, Func valueTask) 16 | { 17 | var maybe = await maybeTask; 18 | 19 | if (maybe.HasValue) 20 | return; 21 | 22 | await valueTask(); 23 | } 24 | 25 | } 26 | } 27 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/ExecuteNoValue.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class MaybeExtensions 6 | { 7 | /// 8 | /// Executes the given if the has no value 9 | /// 10 | /// 11 | /// 12 | /// 13 | public static void ExecuteNoValue(in this Maybe maybe, Action action) 14 | { 15 | if (maybe.HasValue) 16 | return; 17 | 18 | action(); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Flatten.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpFunctionalExtensions 2 | { 3 | public static partial class MaybeExtensions 4 | { 5 | /// 6 | /// Flattens nested s into a single . 7 | /// 8 | /// The flattened . 9 | public static Maybe Flatten(in this Maybe> maybe) 10 | { 11 | return maybe.GetValueOrDefault(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/GetValueOrDefault.Task.Left.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | public static async Task GetValueOrDefault(this Task> maybeTask, Func defaultValue) 9 | { 10 | var maybe = await maybeTask.DefaultAwait(); 11 | return maybe.GetValueOrDefault(defaultValue); 12 | } 13 | 14 | public static async Task GetValueOrDefault(this Task> maybeTask, Func selector, 15 | K defaultValue = default) 16 | { 17 | var maybe = await maybeTask.DefaultAwait(); 18 | return maybe.GetValueOrDefault(selector, defaultValue); 19 | } 20 | 21 | public static async Task GetValueOrDefault(this Task> maybeTask, Func selector, 22 | Func defaultValue) 23 | { 24 | var maybe = await maybeTask.DefaultAwait(); 25 | return maybe.GetValueOrDefault(selector, defaultValue); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/GetValueOrDefault.Task.Right.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | public static async Task GetValueOrDefault(this Maybe maybe, Func> defaultValue) 9 | { 10 | if (maybe.HasNoValue) 11 | return await defaultValue().DefaultAwait(); 12 | 13 | return maybe.GetValueOrThrow(); 14 | } 15 | 16 | public static async Task GetValueOrDefault(this Maybe maybe, Func selector, 17 | Func> defaultValue) 18 | { 19 | if (maybe.HasNoValue) 20 | return await defaultValue().DefaultAwait(); 21 | 22 | return selector(maybe.GetValueOrThrow()); 23 | } 24 | 25 | public static async Task GetValueOrDefault(this Maybe maybe, Func> selector, 26 | K defaultValue = default) 27 | { 28 | if (maybe.HasNoValue) 29 | return defaultValue; 30 | 31 | return await selector(maybe.GetValueOrThrow()).DefaultAwait(); 32 | } 33 | 34 | public static async Task GetValueOrDefault(this Maybe maybe, Func> selector, 35 | Func> defaultValue) 36 | { 37 | if (maybe.HasNoValue) 38 | return await defaultValue().DefaultAwait(); 39 | 40 | return await selector(maybe.GetValueOrThrow()).DefaultAwait(); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/GetValueOrDefault.Task.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | public static async Task GetValueOrDefault(this Task> maybeTask, Func> defaultValue) 9 | { 10 | var maybe = await maybeTask.DefaultAwait(); 11 | return await maybe.GetValueOrDefault(defaultValue).DefaultAwait(); 12 | } 13 | 14 | public static async Task GetValueOrDefault(this Task> maybeTask, Func> selector, 15 | K defaultValue = default) 16 | { 17 | var maybe = await maybeTask.DefaultAwait(); 18 | return await maybe.GetValueOrDefault(selector, defaultValue).DefaultAwait(); 19 | } 20 | 21 | public static async Task GetValueOrDefault(this Task> maybeTask, Func> selector, 22 | Func> defaultValue) 23 | { 24 | var maybe = await maybeTask.DefaultAwait(); 25 | return await maybe.GetValueOrDefault(selector, defaultValue).DefaultAwait(); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/GetValueOrDefault.ValueTask.Left.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | public static async ValueTask GetValueOrDefault(this ValueTask> maybeTask, Func defaultValue) 10 | { 11 | var maybe = await maybeTask; 12 | return maybe.GetValueOrDefault(defaultValue); 13 | } 14 | 15 | public static async ValueTask GetValueOrDefault(this ValueTask> maybeTask, Func selector, 16 | K defaultValue = default) 17 | { 18 | var maybe = await maybeTask; 19 | return maybe.GetValueOrDefault(selector, defaultValue); 20 | } 21 | 22 | public static async ValueTask GetValueOrDefault(this ValueTask> maybeTask, Func selector, 23 | Func defaultValue) 24 | { 25 | var maybe = await maybeTask; 26 | return maybe.GetValueOrDefault(selector, defaultValue); 27 | } 28 | } 29 | } 30 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/GetValueOrDefault.ValueTask.Right.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | public static async ValueTask GetValueOrDefault(this Maybe maybe, Func> valueTask) 10 | { 11 | if (maybe.HasNoValue) 12 | return await valueTask(); 13 | 14 | return maybe.GetValueOrThrow(); 15 | } 16 | 17 | public static async ValueTask GetValueOrDefault(this Maybe maybe, Func selector, 18 | Func> valueTask) 19 | { 20 | if (maybe.HasNoValue) 21 | return await valueTask(); 22 | 23 | return selector(maybe.GetValueOrThrow()); 24 | } 25 | 26 | public static async ValueTask GetValueOrDefault(this Maybe maybe, Func> valueTask, 27 | K defaultValue = default) 28 | { 29 | if (maybe.HasNoValue) 30 | return defaultValue; 31 | 32 | return await valueTask(maybe.GetValueOrThrow()); 33 | } 34 | 35 | public static async ValueTask GetValueOrDefault(this Maybe maybe, Func> valueTask, 36 | Func> defaultValue) 37 | { 38 | if (maybe.HasNoValue) 39 | return await defaultValue(); 40 | 41 | return await valueTask(maybe.GetValueOrThrow()); 42 | } 43 | } 44 | } 45 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/GetValueOrDefault.ValueTask.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | public static async ValueTask GetValueOrDefault(this ValueTask> maybeTask, Func> defaultValue) 10 | { 11 | var maybe = await maybeTask; 12 | return await maybe.GetValueOrDefault(defaultValue); 13 | } 14 | 15 | public static async ValueTask GetValueOrDefault(this ValueTask> maybeTask, Func> selector, 16 | K defaultValue = default) 17 | { 18 | var maybe = await maybeTask; 19 | return await maybe.GetValueOrDefault(selector, defaultValue); 20 | } 21 | 22 | public static async ValueTask GetValueOrDefault(this ValueTask> maybeTask, Func> selector, 23 | Func> defaultValue) 24 | { 25 | var maybe = await maybeTask; 26 | return await maybe.GetValueOrDefault(selector, defaultValue); 27 | } 28 | } 29 | } 30 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/GetValueOrDefault.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class MaybeExtensions 6 | { 7 | public static T GetValueOrDefault(in this Maybe maybe, Func defaultValue) 8 | { 9 | if (maybe.HasNoValue) 10 | return defaultValue(); 11 | 12 | return maybe.GetValueOrThrow(); 13 | } 14 | 15 | public static K GetValueOrDefault(in this Maybe maybe, Func selector, K defaultValue = default) 16 | { 17 | if (maybe.HasNoValue) 18 | return defaultValue; 19 | 20 | return selector(maybe.GetValueOrThrow()); 21 | } 22 | 23 | public static K GetValueOrDefault(in this Maybe maybe, Func selector, Func defaultValue) 24 | { 25 | if (maybe.HasNoValue) 26 | return defaultValue(); 27 | 28 | return selector(maybe.GetValueOrThrow()); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/GetValueOrThrow.Task.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class MaybeExtensions 6 | { 7 | public static async Task GetValueOrThrow(this Task> maybeTask) 8 | { 9 | var maybe = await maybeTask.DefaultAwait(); 10 | return maybe.GetValueOrThrow(); 11 | } 12 | 13 | /// 14 | /// Returns 's inner value if it has one, otherwise throws an InvalidOperationException 15 | /// with 16 | /// 17 | /// Maybe has no value. 18 | public static async Task GetValueOrThrow(this Task> maybeTask, string errorMessage) 19 | { 20 | var maybe = await maybeTask.DefaultAwait(); 21 | return maybe.GetValueOrThrow(errorMessage); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/GetValueOrThrow.ValueTask.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | public static async ValueTask GetValueOrThrow(this ValueTask> maybeTask) 10 | { 11 | var maybe = await maybeTask; 12 | return maybe.GetValueOrThrow(); 13 | } 14 | 15 | /// 16 | /// Returns 's inner value if it has one, otherwise throws an InvalidOperationException 17 | /// with 18 | /// 19 | /// Maybe has no value. 20 | public static async ValueTask GetValueOrThrow(this ValueTask> maybeTask, string errorMessage) 21 | { 22 | var maybe = await maybeTask; 23 | return maybe.GetValueOrThrow(errorMessage); 24 | } 25 | } 26 | } 27 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Map.Task.Left.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | public static async Task> Map( 9 | this Task> maybeTask, 10 | Func selector 11 | ) 12 | { 13 | var maybe = await maybeTask.DefaultAwait(); 14 | return maybe.Map(selector); 15 | } 16 | 17 | public static async Task> Map( 18 | this Task> maybeTask, 19 | Func selector, 20 | TContext context 21 | ) 22 | { 23 | var maybe = await maybeTask.DefaultAwait(); 24 | return maybe.Map(selector, context); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Map.Task.Right.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | public static async Task> Map(this Maybe maybe, Func> selector) 9 | { 10 | if (maybe.HasNoValue) 11 | return Maybe.None; 12 | 13 | return await selector(maybe.GetValueOrThrow()).DefaultAwait(); 14 | } 15 | 16 | public static async Task> Map( 17 | this Maybe maybe, 18 | Func> selector, 19 | TContext context 20 | ) 21 | { 22 | if (maybe.HasNoValue) 23 | return Maybe.None; 24 | 25 | return await selector(maybe.GetValueOrThrow(), context).DefaultAwait(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Map.Task.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | public static async Task> Map( 9 | this Task> maybeTask, 10 | Func> selector 11 | ) 12 | { 13 | var maybe = await maybeTask.DefaultAwait(); 14 | return await maybe.Map(selector).DefaultAwait(); 15 | } 16 | 17 | public static async Task> Map( 18 | this Task> maybeTask, 19 | Func> selector, 20 | TContext context 21 | ) 22 | { 23 | var maybe = await maybeTask.DefaultAwait(); 24 | return await maybe.Map(selector, context).DefaultAwait(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Map.ValueTask.Left.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | public static async ValueTask> Map( 10 | this ValueTask> valueTask, 11 | Func selector 12 | ) 13 | { 14 | Maybe maybe = await valueTask; 15 | return maybe.Map(selector); 16 | } 17 | 18 | public static async ValueTask> Map( 19 | this ValueTask> valueTask, 20 | Func selector, 21 | TContext context 22 | ) 23 | { 24 | Maybe maybe = await valueTask; 25 | return maybe.Map(selector, context); 26 | } 27 | } 28 | } 29 | #endif 30 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Map.ValueTask.Right.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | public static async ValueTask> Map( 10 | this Maybe maybe, 11 | Func> valueTask 12 | ) 13 | { 14 | if (maybe.HasNoValue) 15 | return Maybe.None; 16 | 17 | return await valueTask(maybe.GetValueOrThrow()); 18 | } 19 | 20 | public static async ValueTask> Map( 21 | this Maybe maybe, 22 | Func> valueTask, 23 | TContext context 24 | ) 25 | { 26 | if (maybe.HasNoValue) 27 | return Maybe.None; 28 | 29 | return await valueTask(maybe.GetValueOrThrow(), context); 30 | } 31 | } 32 | } 33 | #endif 34 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Map.ValueTask.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | public static async ValueTask> Map( 10 | this ValueTask> maybeTask, 11 | Func> valueTask 12 | ) 13 | { 14 | Maybe maybe = await maybeTask; 15 | return await maybe.Map(valueTask); 16 | } 17 | 18 | public static async ValueTask> Map( 19 | this ValueTask> maybeTask, 20 | Func> valueTask, 21 | TContext context 22 | ) 23 | { 24 | Maybe maybe = await maybeTask; 25 | return await maybe.Map(valueTask, context); 26 | } 27 | } 28 | } 29 | #endif 30 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Map.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class MaybeExtensions 6 | { 7 | public static Maybe Map(in this Maybe maybe, Func selector) 8 | { 9 | if (maybe.HasNoValue) 10 | return Maybe.None; 11 | 12 | return selector(maybe.GetValueOrThrow()); 13 | } 14 | 15 | public static Maybe Map( 16 | in this Maybe maybe, 17 | Func selector, 18 | TContext context 19 | ) 20 | { 21 | if (maybe.HasNoValue) 22 | return Maybe.None; 23 | 24 | return selector(maybe.GetValueOrThrow(), context); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Optional.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpFunctionalExtensions 2 | { 3 | public static partial class MaybeExtensions 4 | { 5 | /// 6 | /// Mark the possibly null value as optional. Null is not an error, it's just null. 7 | /// 8 | public static Result, E> Optional(this Maybe> maybe) 9 | { 10 | if (maybe.HasNoValue) 11 | return Result.Success, E>(Maybe.None); 12 | 13 | if (maybe.Value.IsFailure) 14 | return Result.Failure, E>(maybe.Value.Error); 15 | 16 | return Result.Success, E>(Maybe.From(maybe.Value.Value)); 17 | } 18 | 19 | /// 20 | /// Mark the possibly null value as optional. Null is not an error, it's just null. 21 | /// 22 | public static Result> Optional(this Maybe> maybe) 23 | { 24 | if (maybe.HasNoValue) 25 | return Result.Success>(Maybe.None); 26 | 27 | if (maybe.Value.IsFailure) 28 | return Result.Failure>(maybe.Value.Error); 29 | 30 | return Result.Success>(Maybe.From(maybe.Value.Value)); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Select.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | public static Maybe Select(in this Maybe maybe, Func selector) 9 | { 10 | return maybe.Map(selector); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/SelectMany.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class MaybeExtensions 6 | { 7 | public static Maybe SelectMany(in this Maybe maybe, Func> selector) 8 | { 9 | return maybe.Bind(selector); 10 | } 11 | 12 | public static Maybe SelectMany(in this Maybe maybe, 13 | Func> selector, 14 | Func project) 15 | { 16 | return maybe.GetValueOrDefault( 17 | x => selector(x).GetValueOrDefault(u => project(x, u), Maybe.None), 18 | Maybe.None); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/ToInvertedResult.Task.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | public static async Task ToInvertedResult(this Task> maybeTask, string errorMessage) 9 | { 10 | var maybe = await maybeTask.DefaultAwait(); 11 | return maybe.ToInvertedResult(errorMessage); 12 | } 13 | 14 | public static async Task> ToInvertedResult(this Task> maybeTask, E error) 15 | { 16 | var maybe = await maybeTask.DefaultAwait(); 17 | return maybe.ToInvertedResult(error); 18 | } 19 | 20 | public static async Task> ToInvertedResult(this Task> maybeTask, Func errorFunc) 21 | { 22 | var maybe = await maybeTask.DefaultAwait(); 23 | return maybe.ToInvertedResult(errorFunc); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/ToInvertedResult.ValueTask.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | public static async ValueTask ToInvertedResult(this ValueTask> maybeTask, string errorMessage) 10 | { 11 | Maybe maybe = await maybeTask; 12 | return maybe.ToInvertedResult(errorMessage); 13 | } 14 | 15 | public static async ValueTask> ToInvertedResult(this ValueTask> maybeTask, E error) 16 | { 17 | Maybe maybe = await maybeTask; 18 | return maybe.ToInvertedResult(error); 19 | } 20 | 21 | public static async ValueTask> ToInvertedResult(this ValueTask> maybeTask, Func errorFunc) 22 | { 23 | Maybe maybe = await maybeTask; 24 | return maybe.ToInvertedResult(errorFunc); 25 | } 26 | } 27 | } 28 | #endif 29 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/ToInvertedResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class MaybeExtensions 6 | { 7 | public static Result ToInvertedResult(in this Maybe maybe, string errorMessage) 8 | { 9 | if (maybe.HasValue) 10 | return Result.Failure(errorMessage); 11 | 12 | return Result.Success(); 13 | } 14 | 15 | public static UnitResult ToInvertedResult(in this Maybe maybe, E error) 16 | { 17 | if (maybe.HasValue) 18 | return UnitResult.Failure(error); 19 | 20 | return UnitResult.Success(); 21 | } 22 | 23 | public static UnitResult ToInvertedResult(in this Maybe maybe, Func errorFunc) 24 | { 25 | if (maybe.HasValue) 26 | return UnitResult.Failure(errorFunc()); 27 | 28 | return UnitResult.Success(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/ToList.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class MaybeExtensions 6 | { 7 | public static List ToList(in this Maybe maybe) 8 | { 9 | return maybe.GetValueOrDefault(value => new List { value }, new List()); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/ToResult.Task.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | public static async Task> ToResult(this Task> maybeTask, string errorMessage) 9 | { 10 | var maybe = await maybeTask.DefaultAwait(); 11 | return maybe.ToResult(errorMessage); 12 | } 13 | 14 | public static async Task> ToResult(this Task> maybeTask, E error) 15 | { 16 | var maybe = await maybeTask.DefaultAwait(); 17 | return maybe.ToResult(error); 18 | } 19 | 20 | public static async Task> ToResult(this Task> maybeTask, Func errorFunc) 21 | { 22 | var maybe = await maybeTask.DefaultAwait(); 23 | return maybe.ToResult(errorFunc); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/ToResult.ValueTask.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | public static async ValueTask> ToResult(this ValueTask> maybeTask, string errorMessage) 10 | { 11 | Maybe maybe = await maybeTask; 12 | return maybe.ToResult(errorMessage); 13 | } 14 | 15 | public static async ValueTask> ToResult(this ValueTask> maybeTask, E error) 16 | { 17 | Maybe maybe = await maybeTask; 18 | return maybe.ToResult(error); 19 | } 20 | 21 | public static async ValueTask> ToResult(this ValueTask> maybeTask, Func errorFunc) 22 | { 23 | Maybe maybe = await maybeTask; 24 | return maybe.ToResult(errorFunc); 25 | } 26 | } 27 | } 28 | #endif 29 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/ToResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class MaybeExtensions 6 | { 7 | public static Result ToResult(in this Maybe maybe, string errorMessage) 8 | { 9 | if (maybe.HasNoValue) 10 | return Result.Failure(errorMessage); 11 | 12 | return Result.Success(maybe.GetValueOrThrow()); 13 | } 14 | 15 | public static Result ToResult(in this Maybe maybe, E error) 16 | { 17 | if (maybe.HasNoValue) 18 | return Result.Failure(error); 19 | 20 | return Result.Success(maybe.GetValueOrThrow()); 21 | } 22 | 23 | public static Result ToResult(in this Maybe maybe, Func errorFunc) 24 | { 25 | if (maybe.HasNoValue) 26 | return Result.Failure(errorFunc()); 27 | 28 | return Result.Success(maybe.GetValueOrThrow()); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/ToUnitResult.Task.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | public static async Task> ToUnitResult(this Task> maybeTask) 9 | { 10 | var maybe = await maybeTask.DefaultAwait(); 11 | return maybe.ToUnitResult(); 12 | } 13 | 14 | public static async Task> ToUnitResult(this Task> maybeTask, E error) 15 | { 16 | var maybe = await maybeTask.DefaultAwait(); 17 | return maybe.ToUnitResult(error); 18 | } 19 | 20 | public static async Task> ToUnitResult(this Task> maybeTask, Func errorFunc) 21 | { 22 | var maybe = await maybeTask.DefaultAwait(); 23 | return maybe.ToUnitResult(errorFunc); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/ToUnitResult.ValueTask.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | public static async ValueTask> ToUnitResult(this ValueTask> maybeTask) 10 | { 11 | Maybe maybe = await maybeTask; 12 | return maybe.ToUnitResult(); 13 | } 14 | 15 | public static async ValueTask> ToUnitResult(this ValueTask> maybeTask, E error) 16 | { 17 | Maybe maybe = await maybeTask; 18 | return maybe.ToUnitResult(error); 19 | } 20 | 21 | public static async ValueTask> ToUnitResult(this ValueTask> maybeTask, Func errorFunc) 22 | { 23 | Maybe maybe = await maybeTask; 24 | return maybe.ToUnitResult(errorFunc); 25 | } 26 | } 27 | } 28 | #endif 29 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/ToUnitResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class MaybeExtensions 6 | { 7 | public static UnitResult ToUnitResult(in this Maybe maybe) 8 | { 9 | if (maybe.HasValue) 10 | return UnitResult.Failure(maybe.Value); 11 | 12 | return UnitResult.Success(); 13 | } 14 | 15 | public static UnitResult ToUnitResult(in this Maybe maybe, E error) 16 | { 17 | if (maybe.HasNoValue) 18 | return UnitResult.Failure(error); 19 | 20 | return UnitResult.Success(); 21 | } 22 | 23 | public static UnitResult ToUnitResult(in this Maybe maybe, Func errorFunc) 24 | { 25 | if (maybe.HasNoValue) 26 | return UnitResult.Failure(errorFunc()); 27 | 28 | return UnitResult.Success(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/TryFind.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class MaybeExtensions 6 | { 7 | #if !NET45_OR_GREATER && !NETSTANDARD && !NETCORE && !NET 8 | public static Maybe TryFind(this IDictionary dict, K key) 9 | { 10 | if (dict.ContainsKey(key)) return dict[key]; 11 | 12 | return Maybe.None; 13 | } 14 | #else 15 | public static Maybe TryFind(this IReadOnlyDictionary dict, K key) 16 | { 17 | if (dict.ContainsKey(key)) 18 | { 19 | return dict[key]; 20 | } 21 | return Maybe.None; 22 | } 23 | #endif 24 | } 25 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/TryFirst.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace CSharpFunctionalExtensions 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | public static Maybe TryFirst(this IEnumerable source) 10 | { 11 | source = source as ICollection ?? source.ToList(); 12 | 13 | if (source.Any()) return Maybe.From(source.First()); 14 | 15 | return Maybe.None; 16 | } 17 | 18 | public static Maybe TryFirst(this IEnumerable source, Func predicate) 19 | { 20 | var firstOrEmpty = source.Where(predicate).Take(1).ToList(); 21 | if (firstOrEmpty.Any()) return Maybe.From(firstOrEmpty[0]); 22 | 23 | return Maybe.None; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/TryLast.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace CSharpFunctionalExtensions 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | public static Maybe TryLast(this IEnumerable source) 10 | { 11 | source = source as ICollection ?? source.ToList(); 12 | 13 | if (source.Any()) return Maybe.From(source.Last()); 14 | 15 | return Maybe.None; 16 | } 17 | 18 | public static Maybe TryLast(this IEnumerable source, Func predicate) 19 | { 20 | var last = source.LastOrDefault(predicate); 21 | if (last != null) return Maybe.From(last); 22 | 23 | return Maybe.None; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Where.Task.Left.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | public static async Task> Where(this Task> maybeTask, Func predicate) 9 | { 10 | var maybe = await maybeTask.DefaultAwait(); 11 | return maybe.Where(predicate); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Where.Task.Right.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | public static async Task> Where(this Maybe maybe, Func> predicate) 9 | { 10 | if (maybe.HasNoValue) 11 | return Maybe.None; 12 | 13 | if (await predicate(maybe.GetValueOrThrow()).DefaultAwait()) 14 | return maybe; 15 | 16 | return Maybe.None; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Where.Task.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class MaybeExtensions 7 | { 8 | public static async Task> Where(this Task> maybeTask, Func> predicate) 9 | { 10 | var maybe = await maybeTask.DefaultAwait(); 11 | return await maybe.Where(predicate).DefaultAwait(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Where.ValueTask.Left.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | public static async ValueTask> Where(this ValueTask> maybeTask, Func predicate) 10 | { 11 | Maybe maybe = await maybeTask; 12 | return maybe.Where(predicate); 13 | } 14 | } 15 | } 16 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Where.ValueTask.Right.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | public static async ValueTask> Where(this Maybe maybe, Func> predicate) 10 | { 11 | if (maybe.HasNoValue) 12 | return Maybe.None; 13 | 14 | if (await predicate(maybe.GetValueOrThrow())) 15 | return maybe; 16 | 17 | return Maybe.None; 18 | } 19 | } 20 | } 21 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Where.ValueTask.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class MaybeExtensions 8 | { 9 | public static async ValueTask> Where(this ValueTask> maybeTask, Func> predicate) 10 | { 11 | Maybe maybe = await maybeTask; 12 | return await maybe.Where(predicate); 13 | } 14 | } 15 | } 16 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Extensions/Where.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class MaybeExtensions 6 | { 7 | public static Maybe Where(in this Maybe maybe, Func predicate) 8 | { 9 | if (maybe.HasNoValue) 10 | return Maybe.None; 11 | 12 | if (predicate(maybe.GetValueOrThrow())) 13 | return maybe; 14 | 15 | return Maybe.None; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/Maybe.Configuration.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpFunctionalExtensions 2 | { 3 | public readonly partial struct Maybe 4 | { 5 | private static class Configuration 6 | { 7 | public static string NoValueException = "Maybe has no value."; 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Maybe/MaybeEqualityComparer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public class MaybeEqualityComparer : IEqualityComparer> 6 | { 7 | private readonly IEqualityComparer _equalityComparer; 8 | 9 | public MaybeEqualityComparer(IEqualityComparer equalityComparer = null) 10 | { 11 | _equalityComparer = equalityComparer ?? EqualityComparer.Default; 12 | } 13 | 14 | public bool Equals(Maybe x, Maybe y) 15 | { 16 | if (x.HasNoValue && y.HasNoValue) 17 | { 18 | return true; 19 | } 20 | 21 | return x.HasValue && y.HasValue && _equalityComparer.Equals(x.Value, y.Value); 22 | } 23 | 24 | public int GetHashCode(Maybe obj) 25 | { 26 | return obj.HasNoValue ? 0 : _equalityComparer.GetHashCode(obj.Value); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Exceptions/ResultFailureException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public class ResultFailureException : Exception 6 | { 7 | public string Error { get; } 8 | 9 | internal ResultFailureException(string error) 10 | : base(Result.Messages.ValueIsInaccessibleForFailure(error)) 11 | { 12 | Error = error; 13 | } 14 | } 15 | 16 | public class ResultFailureException : ResultFailureException 17 | { 18 | public new E Error { get; } 19 | 20 | internal ResultFailureException(E error) 21 | : base(Result.Messages.ValueIsInaccessibleForFailure(error.ToString())) 22 | { 23 | Error = error; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Exceptions/ResultSuccessException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public class ResultSuccessException : Exception 6 | { 7 | internal ResultSuccessException() 8 | : base(Result.Messages.ErrorIsInaccessibleForSuccess) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/IResult.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpFunctionalExtensions 2 | { 3 | public interface IResult 4 | { 5 | bool IsFailure { get; } 6 | bool IsSuccess { get; } 7 | } 8 | 9 | public interface IValue 10 | { 11 | T Value { get; } 12 | } 13 | 14 | public interface IError 15 | { 16 | E Error { get; } 17 | } 18 | 19 | public interface IResult : IValue, IUnitResult 20 | { 21 | } 22 | 23 | public interface IResult : IResult 24 | { 25 | } 26 | 27 | public interface IUnitResult : IResult, IError 28 | { 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Internal/Result.Messages.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpFunctionalExtensions 2 | { 3 | public partial struct Result 4 | { 5 | internal static class Messages 6 | { 7 | public static readonly string ErrorIsInaccessibleForSuccess = 8 | "You attempted to access the Error property for a successful result. A successful result has no Error."; 9 | 10 | public static string ValueIsInaccessibleForFailure(string error) => 11 | $"You attempted to access the Value property for a failed result. A failed result has no Value. The error was: {error}"; 12 | 13 | public static readonly string ErrorObjectIsNotProvidedForFailure = 14 | "You attempted to create a failure result, which must have an error, but a null error object (or empty string) was passed to the constructor."; 15 | 16 | public static readonly string ErrorObjectIsProvidedForSuccess = 17 | "You attempted to create a success result, which cannot have an error, but a non-null error object was passed to the constructor."; 18 | 19 | public static readonly string ConvertFailureExceptionOnSuccess = 20 | $"{nameof(ConvertFailure)} failed because the Result is in a success state."; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Internal/SerializationValue.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpFunctionalExtensions 2 | { 3 | internal struct SerializationValue 4 | { 5 | public bool IsFailure { get; } 6 | public E Error { get; } 7 | 8 | internal SerializationValue(bool isFailure, E error) 9 | { 10 | IsFailure = isFailure; 11 | Error = error; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Internal/TaskExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | #if NET40 4 | using Task = System.Threading.Tasks.TaskEx; 5 | using Microsoft.Runtime.CompilerServices; 6 | #else 7 | using Task = System.Threading.Tasks.Task; 8 | using System.Runtime.CompilerServices; 9 | #endif 10 | 11 | namespace CSharpFunctionalExtensions 12 | { 13 | internal static class TaskExtensions 14 | { 15 | public static Task AsCompletedTask(this T obj) => Task.FromResult(obj); 16 | 17 | public static ConfiguredTaskAwaitable DefaultAwait(this System.Threading.Tasks.Task task) => 18 | task.ConfigureAwait(Result.Configuration.DefaultConfigureAwait); 19 | 20 | public static ConfiguredTaskAwaitable DefaultAwait(this Task task) => 21 | task.ConfigureAwait(Result.Configuration.DefaultConfigureAwait); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Internal/ValueTaskExtensions.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions.ValueTasks 5 | { 6 | internal static class ValueTaskExtensions 7 | { 8 | public static ValueTask AsCompletedValueTask(this T obj) => ValueTask.FromResult(obj); 9 | } 10 | } 11 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Json/Serialization/CSharpFunctionalExtensionsJsonSerializerOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | 4 | namespace CSharpFunctionalExtensions.Json.Serialization 5 | { 6 | public static class CSharpFunctionalExtensionsJsonSerializerOptions 7 | { 8 | private static readonly Lazy LazyOptions = new(() => 9 | { 10 | var options = new JsonSerializerOptions(JsonSerializerDefaults.Web); 11 | options.AddCSharpFunctionalExtensionsConverters(); 12 | return options; 13 | }); 14 | 15 | public static JsonSerializerOptions Options => LazyOptions.Value; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Json/Serialization/DtoMessages.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | 3 | namespace CSharpFunctionalExtensions.Json.Serialization 4 | { 5 | internal static class DtoMessages 6 | { 7 | public static readonly string HttpResponseMessageIsNull = "HttpResponseMessage is null"; 8 | 9 | public static readonly string ContentJsonNotResult = "The response content in not a Result"; 10 | 11 | public static string NotSuccessStatusCodeFormat(HttpStatusCode statusCode, string content) => $"HttpStatus code is {statusCode}, Content {content}"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Json/Serialization/JsonSerializerOptionsExtensionMethods.cs: -------------------------------------------------------------------------------- 1 | using C2i.Common.C2iCSharpFunctionalExtensions.FunctionalApiResult; 2 | 3 | using System.Text.Json; 4 | 5 | namespace CSharpFunctionalExtensions.Json.Serialization 6 | { 7 | public static class JsonSerializerOptionsExtensionMethods 8 | { 9 | public static JsonSerializerOptions AddCSharpFunctionalExtensionsConverters(this JsonSerializerOptions options) 10 | { 11 | options.Converters.Add(new ResultJsonConverter()); 12 | options.Converters.Add(new ResultOfTJsonConverterFactory()); 13 | options.Converters.Add(new ResultOfTEJsonConverterFactory()); 14 | options.Converters.Add(new UnitResultJsonConverterFactory()); 15 | 16 | return options; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Json/Serialization/ResultDto.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | using System.Text.Json.Serialization; 3 | 4 | namespace CSharpFunctionalExtensions.Json.Serialization 5 | { 6 | internal partial record ResultDto 7 | { 8 | public static ResultDto Success() => new(true, (string)null); 9 | public static ResultDto Failure(string error) => new(false, error); 10 | 11 | public static ResultDto Success(TValue value) => new(true, value, null); 12 | public static ResultDto Failure(string error) => new(false, default!, error); 13 | 14 | public static ResultDto Success(TValue value) => new(true, value, default!); 15 | public static ResultDto Failure(TError error) => new(false, default!, error); 16 | } 17 | 18 | internal partial record ResultDto(bool IsSuccess, string? Error); 19 | 20 | internal record ResultDto(bool IsSuccess, TValue Value, string? Error) 21 | : ResultDto(IsSuccess, Value, Error); 22 | 23 | internal record ResultDto(bool IsSuccess, TValue Value, TError? Error); 24 | } 25 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Json/Serialization/ResultJsonConverter.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | using System; 3 | using System.Text.Json; 4 | using System.Text.Json.Serialization; 5 | 6 | namespace CSharpFunctionalExtensions.Json.Serialization 7 | { 8 | internal class ResultJsonConverter : JsonConverter 9 | { 10 | public override Result Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 11 | { 12 | try 13 | { 14 | return ToResult(JsonSerializer.Deserialize(ref reader, options)); 15 | } 16 | catch (JsonException) 17 | { 18 | return Result.Failure(DtoMessages.ContentJsonNotResult); 19 | } 20 | } 21 | 22 | public override void Write(Utf8JsonWriter writer, Result value, JsonSerializerOptions options) 23 | => JsonSerializer.Serialize(writer, ToResultDto(value), options); 24 | 25 | private static Result ToResult(ResultDto? resultDto) 26 | => resultDto is not null 27 | ? resultDto.IsSuccess ? Result.Success() : Result.Failure(resultDto.Error) 28 | : Result.Failure(DtoMessages.ContentJsonNotResult); 29 | 30 | private static ResultDto ToResultDto(Result result) 31 | => result.IsSuccess ? ResultDto.Success() : ResultDto.Failure(result.Error); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Json/Serialization/UnitResultDto.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace CSharpFunctionalExtensions.Json.Serialization 4 | { 5 | /// 6 | /// Alternative entry-point for to avoid ambiguous calls 7 | /// 8 | internal static partial class UnitResultDto 9 | { 10 | /// 11 | /// Creates a failure result with the given error. 12 | /// 13 | public static UnitResultDto Failure(E error) 14 | { 15 | return new UnitResultDto(false, error); 16 | } 17 | 18 | /// 19 | /// Creates a success . 20 | /// 21 | public static UnitResultDto Success() 22 | { 23 | return new UnitResultDto(true); 24 | } 25 | } 26 | 27 | internal record UnitResultDto([property:Required] bool IsSuccess, [property:Required] E? Error = default); 28 | } 29 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/AsMaybe.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpFunctionalExtensions 2 | { 3 | public static partial class ResultExtensions 4 | { 5 | /// 6 | /// Converts a to a : 7 | /// Returns if the result is Success. 8 | /// Returns if the result is Error. 9 | /// 10 | 11 | public static Maybe AsMaybe(this Result result) 12 | { 13 | return result.IsSuccess 14 | ? Maybe.From(result.Value) 15 | : Maybe.None; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/BindWithTransactionScope.Task.Left.cs: -------------------------------------------------------------------------------- 1 | #if NETSTANDARD2_0 || NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions 6 | { 7 | public static partial class ResultExtensions 8 | { 9 | public static Task> BindWithTransactionScope(this Task> self, Func> f) 10 | => WithTransactionScope(() => self.Bind(f)); 11 | 12 | public static Task> BindWithTransactionScope(this Task> self, Func> f) 13 | => WithTransactionScope(() => self.Bind(f)); 14 | 15 | public static Task> BindWithTransactionScope(this Task self, Func> f) 16 | => WithTransactionScope(() => self.Bind(f)); 17 | 18 | public static Task BindWithTransactionScope(this Task> self, Func f) 19 | => WithTransactionScope(() => self.Bind(f)); 20 | 21 | public static Task BindWithTransactionScope(this Task self, Func f) 22 | => WithTransactionScope(() => self.Bind(f)); 23 | } 24 | } 25 | #endif 26 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/BindWithTransactionScope.Task.Right.cs: -------------------------------------------------------------------------------- 1 | #if NETSTANDARD2_0 || NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions 6 | { 7 | public static partial class ResultExtensions 8 | { 9 | public static Task> BindWithTransactionScope(this Result self, Func>> f) 10 | => WithTransactionScope(() => self.Bind(f)); 11 | 12 | public static Task> BindWithTransactionScope(this Result self, Func>> f) 13 | => WithTransactionScope(() => self.Bind(f)); 14 | 15 | public static Task> BindWithTransactionScope(this Result self, Func>> f) 16 | => WithTransactionScope(() => self.Bind(f)); 17 | 18 | public static Task BindWithTransactionScope(this Result self, Func> f) 19 | => WithTransactionScope(() => self.Bind(f)); 20 | 21 | public static Task BindWithTransactionScope(this Result self, Func> f) 22 | => WithTransactionScope(() => self.Bind(f)); 23 | } 24 | } 25 | #endif 26 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/BindWithTransactionScope.Task.cs: -------------------------------------------------------------------------------- 1 | #if NETSTANDARD2_0 || NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions 6 | { 7 | public static partial class ResultExtensions 8 | { 9 | public static Task> BindWithTransactionScope(this Task> self, Func>> f) 10 | => WithTransactionScope(() => self.Bind(f)); 11 | 12 | public static Task> BindWithTransactionScope(this Task> self, Func>> f) 13 | => WithTransactionScope(() => self.Bind(f)); 14 | 15 | public static Task> BindWithTransactionScope(this Task self, Func>> f) 16 | => WithTransactionScope(() => self.Bind(f)); 17 | 18 | public static Task BindWithTransactionScope(this Task> self, Func> f) 19 | => WithTransactionScope(() => self.Bind(f)); 20 | 21 | public static Task BindWithTransactionScope(this Task self, Func> f) 22 | => WithTransactionScope(() => self.Bind(f)); 23 | } 24 | } 25 | #endif 26 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/BindWithTransactionScope.ValueTask.Left.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class ResultExtensions 8 | { 9 | public static ValueTask> BindWithTransactionScope(this ValueTask> self, Func> f) 10 | => WithTransactionScope(() => self.Bind(f)); 11 | 12 | public static ValueTask> BindWithTransactionScope(this ValueTask> self, Func> f) 13 | => WithTransactionScope(() => self.Bind(f)); 14 | 15 | public static ValueTask> BindWithTransactionScope(this ValueTask self, Func> f) 16 | => WithTransactionScope(() => self.Bind(f)); 17 | 18 | public static ValueTask BindWithTransactionScope(this ValueTask> self, Func f) 19 | => WithTransactionScope(() => self.Bind(f)); 20 | 21 | public static ValueTask BindWithTransactionScope(this ValueTask self, Func f) 22 | => WithTransactionScope(() => self.Bind(f)); 23 | } 24 | } 25 | #endif 26 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/BindWithTransactionScope.ValueTask.Right.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class ResultExtensions 8 | { 9 | public static ValueTask> BindWithTransactionScope(this Result self, Func>> f) 10 | => WithTransactionScope(() => self.Bind(f)); 11 | 12 | public static ValueTask> BindWithTransactionScope(this Result self, Func>> f) 13 | => WithTransactionScope(() => self.Bind(f)); 14 | 15 | public static ValueTask> BindWithTransactionScope(this Result self, Func>> f) 16 | => WithTransactionScope(() => self.Bind(f)); 17 | 18 | public static ValueTask BindWithTransactionScope(this Result self, Func> f) 19 | => WithTransactionScope(() => self.Bind(f)); 20 | 21 | public static ValueTask BindWithTransactionScope(this Result self, Func> f) 22 | => WithTransactionScope(() => self.Bind(f)); 23 | } 24 | } 25 | #endif 26 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/BindWithTransactionScope.ValueTask.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class ResultExtensions 8 | { 9 | public static ValueTask> BindWithTransactionScope(this ValueTask> self, Func>> f) 10 | => WithTransactionScope(() => self.Bind(f)); 11 | 12 | public static ValueTask> BindWithTransactionScope(this ValueTask> self, Func>> f) 13 | => WithTransactionScope(() => self.Bind(f)); 14 | 15 | public static ValueTask> BindWithTransactionScope(this ValueTask self, Func>> f) 16 | => WithTransactionScope(() => self.Bind(f)); 17 | 18 | public static ValueTask BindWithTransactionScope(this ValueTask> self, Func> f) 19 | => WithTransactionScope(() => self.Bind(f)); 20 | 21 | public static ValueTask BindWithTransactionScope(this ValueTask self, Func> f) 22 | => WithTransactionScope(() => self.Bind(f)); 23 | } 24 | } 25 | #endif 26 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/BindWithTransactionScope.cs: -------------------------------------------------------------------------------- 1 | #if NETSTANDARD2_0 || NET5_0_OR_GREATER 2 | using System; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class ResultExtensions 7 | { 8 | public static Result BindWithTransactionScope(this Result self, Func> f) 9 | => WithTransactionScope(() => self.Bind(f)); 10 | 11 | public static Result BindWithTransactionScope(this Result self, Func> f) 12 | => WithTransactionScope(() => self.Bind(f)); 13 | 14 | public static Result BindWithTransactionScope(this Result self, Func f) 15 | => WithTransactionScope(() => self.Bind(f)); 16 | 17 | public static Result BindWithTransactionScope(this Result self, Func f) 18 | => WithTransactionScope(() => self.Bind(f)); 19 | 20 | public static Result BindWithTransactionScope(this Result self, Func> f) 21 | => WithTransactionScope(() => self.Bind(f)); 22 | } 23 | } 24 | #endif 25 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/EnsureNot.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class ResultExtensions 6 | { 7 | /// 8 | /// Returns a new failure result if the predicate is true. Otherwise returns the starting result. 9 | /// 10 | public static Result EnsureNot(this Result result, Func test, string error) => 11 | result.Ensure(v => !test(v), error); 12 | 13 | /// 14 | /// Returns a new failure result if the predicate is true. Otherwise returns the starting result. 15 | /// 16 | public static Result EnsureNot(this Result result, Func test, E error) => 17 | result.Ensure(v => !test(v), error); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/EnsureNotNull.ValueTask.Left.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | #nullable enable 3 | 4 | using System; 5 | using System.Threading.Tasks; 6 | 7 | namespace CSharpFunctionalExtensions.ValueTasks 8 | { 9 | public static partial class ResultExtensions 10 | { 11 | public static ValueTask> EnsureNotNull(this ValueTask> resultTask, Func errorFactory) 12 | where T : class 13 | { 14 | return resultTask.Ensure(value => value != null, _ => errorFactory()).Map(value => value!); 15 | } 16 | 17 | public static ValueTask> EnsureNotNull(this ValueTask> resultTask, Func errorFactory) 18 | where T : struct 19 | { 20 | return resultTask.Ensure(value => value != null, _ => errorFactory()).Map(value => value!.Value); 21 | } 22 | 23 | public static ValueTask> EnsureNotNull(this ValueTask> resultTask, Func errorFactory) 24 | where T : class 25 | { 26 | return resultTask.Ensure(value => ValueTask.FromResult(value != null), _ => errorFactory()).Map(value => value!); 27 | } 28 | 29 | public static ValueTask> EnsureNotNull(this ValueTask> resultTask, Func errorFactory) 30 | where T : struct 31 | { 32 | return resultTask.Ensure(value => ValueTask.FromResult(value != null), _ => errorFactory()).Map(value => value!.Value); 33 | } 34 | } 35 | } 36 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/EnsureNotNull.ValueTask.Right.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | #nullable enable 3 | 4 | using System; 5 | using System.Threading.Tasks; 6 | 7 | namespace CSharpFunctionalExtensions.ValueTasks 8 | { 9 | public static partial class ResultExtensions 10 | { 11 | public static ValueTask> EnsureNotNull(this Result result, Func> errorFactory) 12 | where T : class 13 | { 14 | return result.Ensure(value => ValueTask.FromResult(value != null), _ => errorFactory()).Map(value => value!); 15 | } 16 | 17 | public static ValueTask> EnsureNotNull(this Result result, Func> errorFactory) 18 | where T : struct 19 | { 20 | return result.Ensure(value => ValueTask.FromResult(value != null), _ => errorFactory()).Map(value => value!.Value); 21 | } 22 | 23 | public static ValueTask> EnsureNotNull(this Result result, Func> errorFactory) 24 | where T : class 25 | { 26 | return result.Ensure(value => ValueTask.FromResult(value != null), _ => errorFactory()).Map(value => value!); 27 | } 28 | 29 | public static ValueTask> EnsureNotNull(this Result result, Func> errorFactory) 30 | where T : struct 31 | { 32 | return result.Ensure(value => ValueTask.FromResult(value != null), _ => errorFactory()).Map(value => value!.Value); 33 | } 34 | } 35 | } 36 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/Finally.Task.Right.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class AsyncResultExtensionsRightOperand 7 | { 8 | /// 9 | /// Passes the result to the given function (regardless of success/failure state) to yield a final output value. 10 | /// 11 | public static Task Finally(this Result result, Func> func) 12 | => func(result); 13 | 14 | /// 15 | /// Passes the result to the given function (regardless of success/failure state) to yield a final output value. 16 | /// 17 | public static Task Finally(this Result result, Func, Task> func) 18 | => func(result); 19 | 20 | /// 21 | /// Passes the result to the given function (regardless of success/failure state) to yield a final output value. 22 | /// 23 | public static Task Finally(this UnitResult result, Func, Task> func) 24 | => func(result); 25 | 26 | /// 27 | /// Passes the result to the given function (regardless of success/failure state) to yield a final output value. 28 | /// 29 | public static Task Finally(this Result result, Func, Task> func) 30 | => func(result); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/Finally.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class ResultExtensions 6 | { 7 | /// 8 | /// Passes the result to the given function (regardless of success/failure state) to yield a final output value. 9 | /// 10 | public static T Finally(this Result result, Func func) 11 | => func(result); 12 | 13 | /// 14 | /// Passes the result to the given function (regardless of success/failure state) to yield a final output value. 15 | /// 16 | public static K Finally(this Result result, Func, K> func) 17 | => func(result); 18 | 19 | /// 20 | /// Passes the result to the given function (regardless of success/failure state) to yield a final output value. 21 | /// 22 | public static K Finally(this UnitResult result, Func, K> func) 23 | => func(result); 24 | 25 | /// 26 | /// Passes the result to the given function (regardless of success/failure state) to yield a final output value. 27 | /// 28 | public static K Finally(this Result result, Func, K> func) 29 | => func(result); 30 | } 31 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/GetValueOrDefault.Task.Left.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class ResultExtensions 7 | { 8 | public static async Task GetValueOrDefault(this Task> resultTask, Func defaultValue) 9 | { 10 | var result = await resultTask.DefaultAwait(); 11 | return result.GetValueOrDefault(defaultValue); 12 | } 13 | 14 | public static async Task GetValueOrDefault(this Task> resultTask, Func selector, 15 | K defaultValue = default) 16 | { 17 | var result = await resultTask.DefaultAwait(); 18 | return result.GetValueOrDefault(selector, defaultValue); 19 | } 20 | 21 | public static async Task GetValueOrDefault(this Task> resultTask, Func selector, 22 | Func defaultValue) 23 | { 24 | var result = await resultTask.DefaultAwait(); 25 | return result.GetValueOrDefault(selector, defaultValue); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/GetValueOrDefault.Task.Right.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class ResultExtensions 7 | { 8 | public static async Task GetValueOrDefault(this Result result, Func> defaultValue) 9 | { 10 | if (result.IsFailure) 11 | return await defaultValue().DefaultAwait(); 12 | 13 | return result.Value; 14 | } 15 | 16 | public static async Task GetValueOrDefault(this Result result, Func selector, 17 | Func> defaultValue) 18 | { 19 | if (result.IsFailure) 20 | return await defaultValue().DefaultAwait(); 21 | 22 | return selector(result.Value); 23 | } 24 | 25 | public static async Task GetValueOrDefault(this Result result, Func> selector, 26 | K defaultValue = default) 27 | { 28 | if (result.IsFailure) 29 | return defaultValue; 30 | 31 | return await selector(result.Value).DefaultAwait(); 32 | } 33 | 34 | public static async Task GetValueOrDefault(this Result result, Func> selector, 35 | Func> defaultValue) 36 | { 37 | if (result.IsFailure) 38 | return await defaultValue().DefaultAwait(); 39 | 40 | return await selector(result.Value).DefaultAwait(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/GetValueOrDefault.Task.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class ResultExtensions 7 | { 8 | public static async Task GetValueOrDefault(this Task> resultTask, Func> defaultValue) 9 | { 10 | var result = await resultTask.DefaultAwait(); 11 | return await result.GetValueOrDefault(defaultValue).DefaultAwait(); 12 | } 13 | 14 | public static async Task GetValueOrDefault(this Task> resultTask, Func> selector, 15 | K defaultValue = default) 16 | { 17 | var result = await resultTask.DefaultAwait(); 18 | return await result.GetValueOrDefault(selector, defaultValue).DefaultAwait(); 19 | } 20 | 21 | public static async Task GetValueOrDefault(this Task> resultTask, Func> selector, 22 | Func> defaultValue) 23 | { 24 | var result = await resultTask.DefaultAwait(); 25 | return await result.GetValueOrDefault(selector, defaultValue).DefaultAwait(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/GetValueOrDefault.ValueTask.Left.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class ResultExtensions 8 | { 9 | public static async ValueTask GetValueOrDefault(this ValueTask> resultTask, Func defaultValue) 10 | { 11 | var result = await resultTask; 12 | return result.GetValueOrDefault(defaultValue); 13 | } 14 | 15 | public static async ValueTask GetValueOrDefault(this ValueTask> resultTask, Func selector, 16 | K defaultValue = default) 17 | { 18 | var result = await resultTask; 19 | return result.GetValueOrDefault(selector, defaultValue); 20 | } 21 | 22 | public static async ValueTask GetValueOrDefault(this ValueTask> resultTask, Func selector, 23 | Func defaultValue) 24 | { 25 | var result = await resultTask; 26 | return result.GetValueOrDefault(selector, defaultValue); 27 | } 28 | } 29 | } 30 | #endif 31 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/GetValueOrDefault.ValueTask.Right.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class ResultExtensions 8 | { 9 | public static async ValueTask GetValueOrDefault(this Result result, Func> valueTask) 10 | { 11 | if (result.IsFailure) 12 | return await valueTask(); 13 | 14 | return result.Value; 15 | } 16 | 17 | public static async ValueTask GetValueOrDefault(this Result result, Func selector, 18 | Func> valueTask) 19 | { 20 | if (result.IsFailure) 21 | return await valueTask(); 22 | 23 | return selector(result.Value); 24 | } 25 | 26 | public static async ValueTask GetValueOrDefault(this Result result, Func> valueTask, 27 | K defaultValue = default) 28 | { 29 | if (result.IsFailure) 30 | return defaultValue; 31 | 32 | return await valueTask(result.Value); 33 | } 34 | 35 | public static async ValueTask GetValueOrDefault(this Result result, Func> valueTask, 36 | Func> defaultValue) 37 | { 38 | if (result.IsFailure) 39 | return await defaultValue(); 40 | 41 | return await valueTask(result.Value); 42 | } 43 | } 44 | } 45 | #endif 46 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/GetValueOrDefault.ValueTask.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class ResultExtensions 8 | { 9 | public static async ValueTask GetValueOrDefault(this ValueTask> resultTask, Func> defaultValue) 10 | { 11 | var result = await resultTask; 12 | return await result.GetValueOrDefault(defaultValue); 13 | } 14 | 15 | public static async ValueTask GetValueOrDefault(this ValueTask> resultTask, Func> selector, 16 | K defaultValue = default) 17 | { 18 | var result = await resultTask; 19 | return await result.GetValueOrDefault(selector, defaultValue); 20 | } 21 | 22 | public static async ValueTask GetValueOrDefault(this ValueTask> resultTask, Func> selector, 23 | Func> defaultValue) 24 | { 25 | var result = await resultTask; 26 | return await result.GetValueOrDefault(selector, defaultValue); 27 | } 28 | } 29 | } 30 | #endif 31 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/GetValueOrDefault.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class ResultExtensions 6 | { 7 | /// 8 | /// Gets the value of the result on success, otherwise returns the value returned by the function. 9 | /// 10 | public static T GetValueOrDefault(in this Result result, Func defaultValue) 11 | { 12 | if (result.IsFailure) 13 | return defaultValue(); 14 | 15 | return result.Value; 16 | } 17 | 18 | /// 19 | /// Gets the value of the result on success, otherwise returns the value returned by the selector when called with the default value function. 20 | /// 21 | public static K GetValueOrDefault(in this Result result, Func selector, K defaultValue = default) 22 | { 23 | if (result.IsFailure) 24 | return defaultValue; 25 | 26 | return selector(result.Value); 27 | } 28 | 29 | /// 30 | /// Gets the value of the result on success, otherwise returns the value returned by the selector when called with the default value function. 31 | /// 32 | public static K GetValueOrDefault(in this Result result, Func selector, Func defaultValue) 33 | { 34 | if (result.IsFailure) 35 | return defaultValue(); 36 | 37 | return selector(result.Value); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/MapWithTransactionScope.Task.Left.cs: -------------------------------------------------------------------------------- 1 | #if NETSTANDARD2_0 || NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions 6 | { 7 | public static partial class ResultExtensions 8 | { 9 | public static Task> MapWithTransactionScope(this Task> self, Func f) 10 | => WithTransactionScope(() => self.Map(f)); 11 | 12 | public static Task> MapWithTransactionScope(this Task self, Func f) 13 | => WithTransactionScope(() => self.Map(f)); 14 | } 15 | } 16 | #endif 17 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/MapWithTransactionScope.Task.Right.cs: -------------------------------------------------------------------------------- 1 | #if NETSTANDARD2_0 || NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions 6 | { 7 | public static partial class ResultExtensions 8 | { 9 | public static Task> MapWithTransactionScope(this Result self, Func> f) 10 | => WithTransactionScope(() => self.Map(f)); 11 | 12 | public static Task> MapWithTransactionScope(this Result self, Func> f) 13 | => WithTransactionScope(() => self.Map(f)); 14 | } 15 | } 16 | #endif 17 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/MapWithTransactionScope.Task.cs: -------------------------------------------------------------------------------- 1 | #if NETSTANDARD2_0 || NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions 6 | { 7 | public static partial class ResultExtensions 8 | { 9 | public static Task> MapWithTransactionScope(this Task> self, Func> f) 10 | => WithTransactionScope(() => self.Map(f)); 11 | 12 | public static Task> MapWithTransactionScope(this Task self, Func> f) 13 | => WithTransactionScope(() => self.Map(f)); 14 | } 15 | } 16 | #endif 17 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/MapWithTransactionScope.ValueTask.Left.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class ResultExtensions 8 | { 9 | public static ValueTask> MapWithTransactionScope(this ValueTask> self, Func f) 10 | => WithTransactionScope(() => self.Map(f)); 11 | 12 | public static ValueTask> MapWithTransactionScope(this ValueTask self, Func f) 13 | => WithTransactionScope(() => self.Map(f)); 14 | } 15 | } 16 | #endif 17 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/MapWithTransactionScope.ValueTask.Right.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class ResultExtensions 8 | { 9 | public static ValueTask> MapWithTransactionScope(this Result self, Func> f) 10 | => WithTransactionScope(() => self.Map(f)); 11 | 12 | public static ValueTask> MapWithTransactionScope(this Result self, Func> f) 13 | => WithTransactionScope(() => self.Map(f)); 14 | } 15 | } 16 | #endif 17 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/MapWithTransactionScope.ValueTask.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class ResultExtensions 8 | { 9 | public static ValueTask> MapWithTransactionScope(this ValueTask> self, Func> f) 10 | => WithTransactionScope(() => self.Map(f)); 11 | 12 | public static ValueTask> MapWithTransactionScope(this ValueTask self, Func> f) 13 | => WithTransactionScope(() => self.Map(f)); 14 | } 15 | } 16 | #endif 17 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/MapWithTransactionScope.cs: -------------------------------------------------------------------------------- 1 | #if NETSTANDARD2_0 || NET5_0_OR_GREATER 2 | using System; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class ResultExtensions 7 | { 8 | public static Result MapWithTransactionScope(this Result self, Func f) 9 | => WithTransactionScope(() => self.Map(f)); 10 | 11 | public static Result MapWithTransactionScope(this Result self, Func f) 12 | => WithTransactionScope(() => self.Map(f)); 13 | } 14 | } 15 | #endif 16 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/OnSuccessTry.Task.Left.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class ResultExtensions 7 | { 8 | public static async Task OnSuccessTry(this Task task, Action action, 9 | Func errorHandler = null) 10 | { 11 | var result = await task.DefaultAwait(); 12 | return result.OnSuccessTry(action, errorHandler); 13 | } 14 | 15 | public static async Task OnSuccessTry(this Task> task, Action action, 16 | Func errorHandler = null) 17 | { 18 | var result = await task.DefaultAwait(); 19 | return result.OnSuccessTry(action, errorHandler); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/OnSuccessTry.Task.Right.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class ResultExtensions 7 | { 8 | public static async Task OnSuccessTry(this Result result, Func func, 9 | Func errorHandler = null) 10 | { 11 | return result.IsFailure 12 | ? result 13 | : await Result.Try(func, errorHandler).DefaultAwait(); 14 | } 15 | 16 | public static async Task OnSuccessTry(this Result result, Func func, 17 | Func errorHandler = null) 18 | { 19 | return result.IsFailure 20 | ? Result.Failure(result.Error) 21 | : await Result.Try(() => func.Invoke(result.Value), errorHandler).DefaultAwait(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/OnSuccessTry.Task.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class ResultExtensions 7 | { 8 | public static async Task OnSuccessTry(this Task task, Func func, 9 | Func errorHandler = null) 10 | { 11 | var result = await task.DefaultAwait(); 12 | return await result.OnSuccessTry(func, errorHandler).DefaultAwait(); 13 | } 14 | 15 | public static async Task OnSuccessTry(this Task> task, Func func, 16 | Func errorHandler = null) 17 | { 18 | var result = await task.DefaultAwait(); 19 | return await result.OnSuccessTry(func, errorHandler).DefaultAwait(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/OnSuccessTry.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class ResultExtensions 6 | { 7 | public static Result OnSuccessTry(this Result result, Action action, Func errorHandler = null) 8 | { 9 | return result.IsFailure 10 | ? result 11 | : Result.Try(action, errorHandler); 12 | } 13 | 14 | public static Result OnSuccessTry(this Result result, Action action, Func errorHandler = null) 15 | { 16 | return result.IsFailure 17 | ? Result.Failure(result.Error) 18 | : Result.Try(() => action(result.Value), errorHandler); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/Required.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpFunctionalExtensions 2 | { 3 | public static partial class ResultExtensions 4 | { 5 | /// 6 | /// The optional value is required, so convert to a failed result if there's no value. 7 | /// 8 | public static Result Required(this Result, E> result, E error) => 9 | result.Bind(value => value.ToResult(error)); 10 | 11 | /// 12 | /// The optional value is required, so convert to a failed result if there's no value. 13 | /// 14 | public static Result Required(this Result> result, string error) => 15 | result.Bind(value => value.ToResult(error)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/Select.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class ResultExtensions 6 | { 7 | /// 8 | /// This method should be used in linq queries. We recommend using Map method. 9 | /// 10 | public static Result Select(in this Result result, Func selector) 11 | { 12 | return result.Map(selector); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/SelectMany.Task.Left.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class ResultExtensions 7 | { 8 | /// 9 | /// This method should be used in linq queries. We recommend using Bind method. 10 | /// 11 | public static async Task> SelectMany( 12 | this Task> resultTask, 13 | Func> func, 14 | Func project) 15 | { 16 | Result result = await resultTask.DefaultAwait(); 17 | return result.SelectMany(func, project); 18 | } 19 | 20 | /// 21 | /// This method should be used in linq queries. We recommend using Bind method. 22 | /// 23 | public static async Task> SelectMany( 24 | this Task> resultTask, 25 | Func> func, 26 | Func project) 27 | { 28 | Result result = await resultTask.DefaultAwait(); 29 | return result.SelectMany(func, project); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/SelectMany.Task.Right.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class ResultExtensions 7 | { 8 | /// 9 | /// This method should be used in linq queries. We recommend using Bind method. 10 | /// 11 | public static Task> SelectMany( 12 | this Result result, 13 | Func>> func, 14 | Func project) 15 | { 16 | return result 17 | .Bind(func) 18 | .Map(x => project(result.Value, x)); 19 | } 20 | 21 | /// 22 | /// This method should be used in linq queries. We recommend using Bind method. 23 | /// 24 | public static Task> SelectMany( 25 | this Result result, 26 | Func>> func, 27 | Func project) 28 | { 29 | return result 30 | .Bind(func) 31 | .Map(x => project(result.Value, x)); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/SelectMany.Task.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public static partial class ResultExtensions 7 | { 8 | /// 9 | /// This method should be used in linq queries. We recommend using Bind method. 10 | /// 11 | public static async Task> SelectMany( 12 | this Task> resultTask, 13 | Func>> func, 14 | Func project) 15 | { 16 | Result result = await resultTask.DefaultAwait(); 17 | return await result.SelectMany(func, project).DefaultAwait(); 18 | } 19 | 20 | /// 21 | /// This method should be used in linq queries. We recommend using Bind method. 22 | /// 23 | public static async Task> SelectMany( 24 | this Task> resultTask, 25 | Func>> func, 26 | Func project) 27 | { 28 | Result result = await resultTask.DefaultAwait(); 29 | return await result.SelectMany(func, project).DefaultAwait(); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/SelectMany.ValueTask.Left.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class ResultExtensions 8 | { 9 | /// 10 | /// This method should be used in linq queries. We recommend using Bind method. 11 | /// 12 | public static async ValueTask> SelectMany( 13 | this ValueTask> resultTask, 14 | Func> valueTask, 15 | Func project) 16 | { 17 | Result result = await resultTask; 18 | return result.SelectMany(valueTask, project); 19 | } 20 | 21 | /// 22 | /// This method should be used in linq queries. We recommend using Bind method. 23 | /// 24 | public static async ValueTask> SelectMany( 25 | this ValueTask> resultTask, 26 | Func> valueTask, 27 | Func project) 28 | { 29 | Result result = await resultTask; 30 | return result.SelectMany(valueTask, project); 31 | } 32 | } 33 | } 34 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/SelectMany.ValueTask.Right.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class ResultExtensions 8 | { 9 | /// 10 | /// This method should be used in linq queries. We recommend using Bind method. 11 | /// 12 | public static ValueTask> SelectMany( 13 | this Result result, 14 | Func>> valueTask, 15 | Func project) 16 | { 17 | return result 18 | .Bind(valueTask) 19 | .Map(x => project(result.Value, x)); 20 | } 21 | 22 | /// 23 | /// This method should be used in linq queries. We recommend using Bind method. 24 | /// 25 | public static ValueTask> SelectMany( 26 | this Result result, 27 | Func>> valueTask, 28 | Func project) 29 | { 30 | return result 31 | .Bind(valueTask) 32 | .Map(x => project(result.Value, x)); 33 | } 34 | } 35 | } 36 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/SelectMany.ValueTask.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions.ValueTasks 6 | { 7 | public static partial class ResultExtensions 8 | { 9 | /// 10 | /// This method should be used in linq queries. We recommend using Bind method. 11 | /// 12 | public static async ValueTask> SelectMany( 13 | this ValueTask> resultTask, 14 | Func>> valueTask, 15 | Func project) 16 | { 17 | Result result = await resultTask; 18 | return await result.SelectMany(valueTask, project); 19 | } 20 | 21 | /// 22 | /// This method should be used in linq queries. We recommend using Bind method. 23 | /// 24 | public static async ValueTask> SelectMany( 25 | this ValueTask> resultTask, 26 | Func>> valueTask, 27 | Func project) 28 | { 29 | Result result = await resultTask; 30 | return await result.SelectMany(valueTask, project); 31 | } 32 | } 33 | } 34 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Extensions/SelectMany.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public static partial class ResultExtensions 6 | { 7 | /// 8 | /// This method should be used in linq queries. We recommend using Bind method. 9 | /// 10 | public static Result SelectMany( 11 | this Result result, 12 | Func> func, 13 | Func project) 14 | { 15 | return result 16 | .Bind(func) 17 | .Map(x => project(result.Value, x)); 18 | } 19 | 20 | /// 21 | /// This method should be used in linq queries. We recommend using Bind method. 22 | /// 23 | public static Result SelectMany( 24 | this Result result, 25 | Func> func, 26 | Func project) 27 | { 28 | return result 29 | .Bind(func) 30 | .Map(x => project(result.Value, x)); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Failure.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpFunctionalExtensions 2 | { 3 | public partial struct Result 4 | { 5 | /// 6 | /// Creates a failure result with the given error message. 7 | /// 8 | public static Result Failure(string error) 9 | { 10 | return new Result(true, error); 11 | } 12 | 13 | /// 14 | /// Creates a failure result with the given error message. 15 | /// 16 | public static Result Failure(string error) 17 | { 18 | return new Result(true, error, default); 19 | } 20 | 21 | /// 22 | /// Creates a failure result with the given error. 23 | /// 24 | public static Result Failure(E error) 25 | { 26 | return new Result(true, error, default); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/FailureIf.Task.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | public partial struct Result 7 | { 8 | /// 9 | /// Creates a result whose success/failure depends on the supplied predicate. Opposite of SuccessIf(). 10 | /// 11 | public static async Task FailureIf(Func> failurePredicate, string error) 12 | { 13 | bool isFailure = await failurePredicate().DefaultAwait(); 14 | return SuccessIf(!isFailure, error); 15 | } 16 | 17 | /// 18 | /// Creates a result whose success/failure depends on the supplied predicate. Opposite of SuccessIf(). 19 | /// 20 | public static async Task> FailureIf(Func> failurePredicate, T value, string error) 21 | { 22 | bool isFailure = await failurePredicate().DefaultAwait(); 23 | return SuccessIf(!isFailure, value, error); 24 | } 25 | 26 | /// 27 | /// Creates a result whose success/failure depends on the supplied predicate. Opposite of SuccessIf(). 28 | /// 29 | public static async Task> FailureIf(Func> failurePredicate, T value, E error) 30 | { 31 | bool isFailure = await failurePredicate().DefaultAwait(); 32 | return SuccessIf(!isFailure, value, error); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/FailureIf.ValueTask.cs: -------------------------------------------------------------------------------- 1 | #if NET5_0_OR_GREATER 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace CSharpFunctionalExtensions 6 | { 7 | public partial struct Result 8 | { 9 | /// 10 | /// Creates a result whose success/failure depends on the supplied predicate. Opposite of SuccessIf(). 11 | /// 12 | public static async ValueTask FailureIf(Func> failurePredicate, string error) 13 | { 14 | bool isFailure = await failurePredicate(); 15 | return SuccessIf(!isFailure, error); 16 | } 17 | 18 | /// 19 | /// Creates a result whose success/failure depends on the supplied predicate. Opposite of SuccessIf(). 20 | /// 21 | public static async ValueTask> FailureIf(Func> failurePredicate, T value, string error) 22 | { 23 | bool isFailure = await failurePredicate(); 24 | return SuccessIf(!isFailure, value, error); 25 | } 26 | 27 | /// 28 | /// Creates a result whose success/failure depends on the supplied predicate. Opposite of SuccessIf(). 29 | /// 30 | public static async ValueTask> FailureIf(Func> failurePredicate, T value, E error) 31 | { 32 | bool isFailure = await failurePredicate(); 33 | return SuccessIf(!isFailure, value, error); 34 | } 35 | } 36 | } 37 | #endif -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/FirstFailureOrSuccess.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpFunctionalExtensions 2 | { 3 | public partial struct Result 4 | { 5 | /// 6 | /// Returns the first failure from the supplied . 7 | /// If there is no failure, a success result is returned. 8 | /// 9 | public static Result FirstFailureOrSuccess(params Result[] results) 10 | { 11 | foreach (Result result in results) 12 | { 13 | if (result.IsFailure) 14 | return result; 15 | } 16 | 17 | return Success(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/Success.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpFunctionalExtensions 2 | { 3 | public partial struct Result 4 | { 5 | /// 6 | /// Creates a success result. 7 | /// 8 | public static Result Success() 9 | { 10 | return new Result(false, default); 11 | } 12 | 13 | /// 14 | /// Creates a success result containing the given value. 15 | /// 16 | public static Result Success(T value) 17 | { 18 | return new Result(false, default, value); 19 | } 20 | 21 | /// 22 | /// Creates a success result containing the given value. 23 | /// 24 | public static Result Success(T value) 25 | { 26 | return new Result(false, default, value); 27 | } 28 | 29 | /// 30 | /// Creates a success result containing the given error. 31 | /// 32 | public static UnitResult Success() 33 | { 34 | return new UnitResult(false, default); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Methods/ToString.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace CSharpFunctionalExtensions 6 | { 7 | public partial struct Result 8 | { 9 | public override string ToString() 10 | { 11 | return IsSuccess ? "Success" : $"Failure({Error})"; 12 | } 13 | } 14 | 15 | 16 | public partial struct Result 17 | { 18 | public override string ToString() 19 | { 20 | return IsSuccess ? $"Success({Value})" : $"Failure({Error})"; 21 | } 22 | } 23 | 24 | 25 | public partial struct Result 26 | { 27 | public override string ToString() 28 | { 29 | return IsSuccess ? $"Success({Value})" : $"Failure({Error})"; 30 | } 31 | } 32 | 33 | 34 | public partial struct UnitResult 35 | { 36 | public override string ToString() 37 | { 38 | return IsSuccess ? "Success" : $"Failure({Error})"; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Result.Configuration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CSharpFunctionalExtensions 4 | { 5 | public partial struct Result 6 | { 7 | public static class Configuration 8 | { 9 | public static string ErrorMessagesSeparator = ", "; 10 | 11 | public static bool DefaultConfigureAwait = false; 12 | 13 | public static Func DefaultTryErrorHandler = exc => exc.Message; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/Result/Result.cs: -------------------------------------------------------------------------------- 1 | using CSharpFunctionalExtensions.Internal; 2 | using System; 3 | using System.Runtime.Serialization; 4 | 5 | namespace CSharpFunctionalExtensions 6 | { 7 | [Serializable] 8 | public readonly partial struct Result : IResult, ISerializable, IError 9 | { 10 | public bool IsFailure { get; } 11 | public bool IsSuccess => !IsFailure; 12 | 13 | private readonly string _error; 14 | public string Error => ResultCommonLogic.GetErrorWithSuccessGuard(IsFailure, _error); 15 | 16 | private Result(bool isFailure, string error) 17 | { 18 | IsFailure = ResultCommonLogic.ErrorStateGuard(isFailure, error); 19 | _error = error; 20 | } 21 | 22 | private Result(SerializationInfo info, StreamingContext context) 23 | { 24 | SerializationValue values = ResultCommonLogic.Deserialize(info); 25 | IsFailure = values.IsFailure; 26 | _error = values.Error; 27 | } 28 | 29 | void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) 30 | { 31 | ResultCommonLogic.GetObjectData(this, info); 32 | } 33 | 34 | public static implicit operator UnitResult(Result result) 35 | { 36 | if (result.IsSuccess) 37 | return UnitResult.Success(); 38 | else 39 | return UnitResult.Failure(result.Error); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/ValueObject/ComparableValueObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace CSharpFunctionalExtensions 7 | { 8 | [Serializable] 9 | public abstract class ComparableValueObject : ValueObject, IComparable, IComparable 10 | { 11 | protected abstract IEnumerable GetComparableEqualityComponents(); 12 | 13 | protected sealed override IEnumerable GetEqualityComponents() => GetComparableEqualityComponents(); 14 | 15 | public virtual int CompareTo(ComparableValueObject other) 16 | { 17 | if (other is null) 18 | return 1; 19 | 20 | if (ReferenceEquals(this, other)) 21 | return 0; 22 | 23 | Type thisType = GetUnproxiedType(this); 24 | Type otherType = GetUnproxiedType(other); 25 | if (thisType != otherType) 26 | return string.Compare($"{thisType}", $"{otherType}", StringComparison.Ordinal); 27 | 28 | return 29 | GetComparableEqualityComponents().Zip( 30 | other.GetComparableEqualityComponents(), 31 | (left, right) => 32 | left?.CompareTo(right) ?? (right is null ? 0 : -1)) 33 | .FirstOrDefault(cmp => cmp != 0); 34 | } 35 | 36 | public virtual int CompareTo(object other) 37 | { 38 | return CompareTo(other as ComparableValueObject); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /CSharpFunctionalExtensions/ValueObject/SimpleValueObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace CSharpFunctionalExtensions 5 | { 6 | [Serializable] 7 | public abstract class SimpleValueObject : ComparableValueObject 8 | where T : IComparable 9 | { 10 | public T Value { get; } 11 | 12 | protected SimpleValueObject(T value) 13 | { 14 | Value = value; 15 | } 16 | 17 | protected override IEnumerable GetComparableEqualityComponents() 18 | { 19 | yield return Value; 20 | } 21 | 22 | public override string ToString() 23 | { 24 | return Value?.ToString(); 25 | } 26 | 27 | public static implicit operator T(SimpleValueObject valueObject) 28 | { 29 | return valueObject == null ? default : valueObject.Value; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Common.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0;net6.0;net8.0 4 | Vladimir Khorikov 5 | CSharpFunctionalExtensions - functional extensions for C# 6 | false 7 | C# Functional Result Maybe ValueObject 8 | MIT 9 | https://enterprisecraftsmanship.com/ps-func 10 | https://github.com/vkhorikov/CSharpFunctionalExtensions/ 11 | en-US 12 | false 13 | 9.0 14 | false 15 | true 16 | true 17 | true 18 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb 19 | 1591;1701;1702 20 | 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Vladimir Khorikov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /version.txt: -------------------------------------------------------------------------------- 1 | 3.6.0 2 | Updates: 3 | * #599 Add extensions for Bind optional, ensure not, map, optional, required 4 | --------------------------------------------------------------------------------