Skip to content

Commit

Permalink
Merge pull request #569 from DerStimmler/feat/async-maybe-from
Browse files Browse the repository at this point in the history
Add async & func overloads for `Maybe.From`
  • Loading branch information
vkhorikov authored Sep 28, 2024
2 parents 9599a06 + d7d6ec9 commit c3ade4b
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 7 deletions.
79 changes: 75 additions & 4 deletions CSharpFunctionalExtensions.Tests/MaybeTests/BasicTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using FluentAssertions;
#nullable enable

using FluentAssertions;
using System;
using System.Threading.Tasks;
using Xunit;

namespace CSharpFunctionalExtensions.Tests.MaybeTests
Expand Down Expand Up @@ -40,7 +43,7 @@ public void Cannot_access_Value_if_none()

Action action = () =>
{
MyClass myClass = maybe.Value;
MyClass _ = maybe.Value;
};

action.Should().Throw<InvalidOperationException>();
Expand Down Expand Up @@ -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<string?> valueTask = Task.FromResult(value)!;

Maybe<string> 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<string> func = () => value;

Maybe<string> 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<string?> valueTask = Task.FromResult(value)!;
Func<Task<string?>> valueTaskFunc = () => valueTask;

Maybe<string> 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<string?> valueTask = Task.FromResult<string?>(null);

Maybe<string> maybe = await Maybe.From(valueTask);

maybe.HasValue.Should().BeFalse();
}

[Fact]
public void Maybe_From_can_create_MaybeT_from_func_with_no_value()
{
Func<string?> func = () => null;

Maybe<string> maybe = Maybe.From(func);

maybe.HasValue.Should().BeFalse();
}

[Fact]
public async Task Maybe_From_can_create_MaybeT_from_valueTaskFunc_with_no_value()
{
Task<string?> valueTask = Task.FromResult<string?>(null);
Func<Task<string?>> valueTaskFunc = () => valueTask;

Maybe<string> maybe = await Maybe.From(valueTaskFunc);

maybe.HasValue.Should().BeFalse();
}

[Fact]
public void Can_cast_non_generic_maybe_none_to_maybe_none()
Expand All @@ -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";

Expand Down Expand Up @@ -168,7 +239,7 @@ public void Maybe_None_doesnt_throw_on_Deconstruct()

Action act = () =>
{
var (hasValue, value) = maybe;
(bool _, int _) = maybe;
};

act.Should().NotThrow();
Expand Down
43 changes: 40 additions & 3 deletions CSharpFunctionalExtensions/Maybe/Maybe.cs
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -103,9 +104,30 @@ public static implicit operator Maybe<T>(T? value)

public static implicit operator Maybe<T>(Maybe value) => None;

public static Maybe<T> From(T? obj)
public static Maybe<T> From(T? value)
{
return new Maybe<T>(obj);
return new Maybe<T>(value);
}

public static Maybe<T> From(Func<T?> func)
{
T? value = func();

return new Maybe<T>(value);
}

public static async Task<Maybe<T>> From(Task<T?> valueTask)
{
T? value = await valueTask;

return new Maybe<T>(value);
}

public static async Task<Maybe<T>> From(Func<Task<T?>> valueTaskFunc)
{
T? value = await valueTaskFunc();

return new Maybe<T>(value);
}

public static bool operator ==(Maybe<T> maybe, T value)
Expand Down Expand Up @@ -188,12 +210,27 @@ public override string ToString()
/// </summary>
public readonly struct Maybe
{
public static Maybe None => new Maybe();
public static Maybe None => new();

/// <summary>
/// Creates a new <see cref="Maybe{T}" /> from the provided <paramref name="value"/>
/// </summary>
public static Maybe<T> From<T>(T? value) => Maybe<T>.From(value);

/// <summary>
/// Creates a new <see cref="Maybe{T}" /> from the provided <paramref name="func"/>
/// </summary>
public static Maybe<T> From<T>(Func<T?> func) => Maybe<T>.From(func);

/// <summary>
/// Creates a new <see cref="Maybe{T}" /> from the provided <paramref name="valueTask"/>
/// </summary>
public static Task<Maybe<T>> From<T>(Task<T?> valueTask) => Maybe<T>.From(valueTask);

/// <summary>
/// Creates a new <see cref="Maybe{T}" /> from the provided <paramref name="valueTaskFunc"/>
/// </summary>
public static Task<Maybe<T>> From<T>(Func<Task<T?>> valueTaskFunc) => Maybe<T>.From(valueTaskFunc);
}

/// <summary>
Expand Down

0 comments on commit c3ade4b

Please sign in to comment.