Search code examples
c#async-await.net-4.6.1

How to write overloads that takes Func<T,Task<T2>> and Func<T,T2> without explicit cast


I have a method that has two overloads

void Foo(Func<T,T2> syncDelegate) {} //1
void Foo(Func<T,Task<T2>> asyncDelegate){} //2

Then I have a Bar method that is implemented like this

async Task<T2> Bar(T input)
{
// some await code here
}

The Foo is then called like this

Foo(Bar); //3

Due to the nature of async/await which unwraps the Task and makes my Bar is equivalent to

T2 Bar(T input)

To make it work, I have to explicitly cast //3 like this

Foo((Func<T,Task<T2>>)Bar); 

Is there any elegant way to avoid this explicit cast?

UPDATE To clarify the purpose of Foo

Foo() is not a method that invokes delegates. It registers the delegate and the delegates will be invoked by a different mechanism. The reason Foo() doesn't have type parameter is because the type parameter is declared at the class level.

Full mockup code can be found here https://dotnetfiddle.net/c6UCpi


Solution

  • I found a very elegant solution: named parameter.

    Instead of calling

    Foo(Bar);
    

    I should call it with explicit named parameter which declared in the OP.

    Foo(asyncDelegate: Bar);
    

    This explicitly tells the compiler to use the async overload and avoid ambiguity without explicit casting.

    View this for full snippet https://dotnetfiddle.net/c6UCpi