diff --git a/CSharpFunctionalExtensions.Tests/MaybeTests/BasicTests.cs b/CSharpFunctionalExtensions.Tests/MaybeTests/BasicTests.cs index e9de9e99..e4249fce 100644 --- a/CSharpFunctionalExtensions.Tests/MaybeTests/BasicTests.cs +++ b/CSharpFunctionalExtensions.Tests/MaybeTests/BasicTests.cs @@ -1,5 +1,8 @@ -using FluentAssertions; +#nullable enable + +using FluentAssertions; using System; +using System.Threading.Tasks; using Xunit; namespace CSharpFunctionalExtensions.Tests.MaybeTests @@ -40,7 +43,7 @@ public void Cannot_access_Value_if_none() Action action = () => { - MyClass myClass = maybe.Value; + MyClass _ = maybe.Value; }; action.Should().Throw(); @@ -125,6 +128,74 @@ public void Maybe_From_without_type_parameter_creates_new_maybe() withoutTypeParam.Should().Be(withTypeParam); withoutTypeParam.Should().NotBe(differentValueTypeParam); } + + [Fact] + public async Task Maybe_From_can_create_MaybeT_from_valueTask() + { + string value = "value"; + Task valueTask = Task.FromResult(value)!; + + Maybe maybe = await Maybe.From(valueTask); + + maybe.HasValue.Should().BeTrue(); + maybe.Value.Should().Be(value); + } + + [Fact] + public void Maybe_From_can_create_MaybeT_from_func() + { + string value = "value"; + Func func = () => value; + + Maybe maybe = Maybe.From(func); + + maybe.HasValue.Should().BeTrue(); + maybe.Value.Should().Be(value); + } + + [Fact] + public async Task Maybe_From_can_create_MaybeT_from_valueTaskFunc() + { + string value = "value"; + Task valueTask = Task.FromResult(value)!; + Func> valueTaskFunc = () => valueTask; + + Maybe maybe = await Maybe.From(valueTaskFunc); + + maybe.HasValue.Should().BeTrue(); + maybe.Value.Should().Be(value); + } + + [Fact] + public async Task Maybe_From_can_create_MaybeT_from_valueTask_with_no_value() + { + Task valueTask = Task.FromResult(null); + + Maybe maybe = await Maybe.From(valueTask); + + maybe.HasValue.Should().BeFalse(); + } + + [Fact] + public void Maybe_From_can_create_MaybeT_from_func_with_no_value() + { + Func func = () => null; + + Maybe maybe = Maybe.From(func); + + maybe.HasValue.Should().BeFalse(); + } + + [Fact] + public async Task Maybe_From_can_create_MaybeT_from_valueTaskFunc_with_no_value() + { + Task valueTask = Task.FromResult(null); + Func> valueTaskFunc = () => valueTask; + + Maybe maybe = await Maybe.From(valueTaskFunc); + + maybe.HasValue.Should().BeFalse(); + } [Fact] public void Can_cast_non_generic_maybe_none_to_maybe_none() @@ -136,7 +207,7 @@ public void Can_cast_non_generic_maybe_none_to_maybe_none() } [Fact] - public void GetValueOrThrww_throws_with_message_if_source_is_empty() + public void GetValueOrThrow_throws_with_message_if_source_is_empty() { const string errorMessage = "Maybe is none"; @@ -168,7 +239,7 @@ public void Maybe_None_doesnt_throw_on_Deconstruct() Action act = () => { - var (hasValue, value) = maybe; + (bool _, int _) = maybe; }; act.Should().NotThrow(); diff --git a/CSharpFunctionalExtensions/Maybe/Maybe.cs b/CSharpFunctionalExtensions/Maybe/Maybe.cs index b45412ea..78c0c0bf 100644 --- a/CSharpFunctionalExtensions/Maybe/Maybe.cs +++ b/CSharpFunctionalExtensions/Maybe/Maybe.cs @@ -1,6 +1,7 @@ #nullable enable using System; using System.Collections.Generic; +using System.Threading.Tasks; #if NET45_OR_GREATER || NETSTANDARD || NETCORE || NET5_0_OR_GREATER using System.Runtime.CompilerServices; #endif @@ -103,9 +104,30 @@ public static implicit operator Maybe(T? value) public static implicit operator Maybe(Maybe value) => None; - public static Maybe From(T? obj) + public static Maybe From(T? value) { - return new Maybe(obj); + return new Maybe(value); + } + + public static Maybe From(Func func) + { + T? value = func(); + + return new Maybe(value); + } + + public static async Task> From(Task valueTask) + { + T? value = await valueTask; + + return new Maybe(value); + } + + public static async Task> From(Func> valueTaskFunc) + { + T? value = await valueTaskFunc(); + + return new Maybe(value); } public static bool operator ==(Maybe maybe, T value) @@ -188,12 +210,27 @@ public override string ToString() /// public readonly struct Maybe { - public static Maybe None => new Maybe(); + public static Maybe None => new(); /// /// Creates a new from the provided /// public static Maybe From(T? value) => Maybe.From(value); + + /// + /// Creates a new from the provided + /// + public static Maybe From(Func func) => Maybe.From(func); + + /// + /// Creates a new from the provided + /// + public static Task> From(Task valueTask) => Maybe.From(valueTask); + + /// + /// Creates a new from the provided + /// + public static Task> From(Func> valueTaskFunc) => Maybe.From(valueTaskFunc); } ///