altmann / FluentResults

A generalised Result object implementation for .NET/C#
MIT License
2.01k stars 112 forks source link

Result.Try ambiguous invocation when using async statement lambdas since 3.11 #179

Open DAHAG-ArisNourbakhsh opened 1 year ago

DAHAG-ArisNourbakhsh commented 1 year ago

Before 3.11.0, these worked and compiled

var resultTask = Result.Try(async () =>
{
    await Task.CompletedTask;

    return new object();
});

var resultTask2 = Result.Try(async () =>
{
    await Task.CompletedTask;
});

but with 3.11.0 onwards I get a CS0121

The call is ambiguous between the following methods or properties: 'Result.Try(Func<Task>, Func<Exception, IError>)' and 'Result.Try(Func<ValueTask>, Func<Exception, IError>)'

I can of course just not do any async statement lambdas and put the code into dedicated methods but for me this feel a bit verbose and makes quick "try async thing inline" inside methods not so quick

static Task<Result> Foo(string input)
{
    return Result.Try(() => FooInternal(input));
}

static async Task FooInternal(string input)
{
    //Do something with the input
    await Task.CompletedTask;
}

instead of

static Task<Result> Foo(string input)
{
    return Result.Try(async () =>
    {
        //Do something with the input
        await Task.CompletedTask;
    });
}

Only 8 months too late with this feedback and honestly I wouldn't even have a good suggestion on how one would give ValueTask + Task support in overloads. I tried to think of any Microsoft written API that receive a Task and return a Task but couldn't think of anything similar.

Btw love your library

saborrie commented 10 months ago

A similar issue in Xunit: https://github.com/xunit/xunit/issues/2808

dguisinger commented 8 months ago

With C# 11 and beyond you can specify the lambda return type:

await Result.Try(async Task () => { ... })

kmc059000 commented 2 months ago

In https://github.com/xunit/xunit/issues/2808, by recommendation from the Roslyn team, they removed all overloads that took a ValueTask.

altmann commented 2 months ago

Interesting. Who used ValueTasks in combination with FluentResults?

I will search for the inital issue to introduce these ValueTask methods and then we can make a decision.

saborrie commented 2 months ago

Looks like both Task and ValueTask were added simultaneously here: 3bb9607, which was PR #146, no mention of ValueTask or even Task for that matter seems to be part of the discussion

kmc059000 commented 2 months ago

@altmann @saborrie this comment on #146 alludes to #143 which added ValueTask support. Not a ton more context, but something.

guillaumeagile commented 2 weeks ago

Hello there, we face the same issuen trying to "Try" with an Asynchronuous method It does not compile: Ambiguous invocation:   FluentResults. Result Try(System. Action, System. Func<System. Exception,FluentResults. IError>) (in class Result)  .......... Try(System. Func, System. Func<System. Exception,FluentResults. IError>) (in class Result) match

Even with await keyword before "Try" method, because this method is not asynch (pretty logical, though)

Do you consider writing a "TryAsync", to make the compiler happy ?