我有一个方法有两个重载
void Foo(Func<T,T2> syncDelegate) {} //1
void Foo(Func<T,Task<T2>> asyncDelegate){} //2
然后我有一个这样实现的Bar方法
async Task<T2> Bar(T input)
{
// some await code here
}
然后Foo
这样被调用
Foo(Bar); //3
由于async / await的性质,它解开了Task并使我的Bar
等效于
T2 Bar(T input)
要使其正常工作,我必须像这样显式投射//3
Foo((Func<T,Task<T2>>)Bar);
是否有任何优雅的方法来避免这种显式转换?
更新 阐明Foo的目的
Foo()不是调用委托的方法。它注册委托,并且委托将通过不同的机制调用。 Foo()没有类型参数的原因是因为类型参数是在类级别声明的。
完整的样机代码可在此处https://dotnetfiddle.net/c6UCpi
中找到答案 0 :(得分:4)
我找到了一个非常优雅的解决方案:命名参数。
代替呼叫
Foo(Bar);
我应该使用在OP中声明的显式命名参数来调用它。
Foo(asyncDelegate: Bar);
这明确地告诉编译器使用异步重载,并且无需显式强制转换就可以避免歧义。
查看此内容以获取完整摘要 https://dotnetfiddle.net/c6UCpi
答案 1 :(得分:-1)
您面临的问题与异步/等待无关,而与具有仅返回类型不同的签名的方法有关。
这可以通过以下简单示例进行演示:
static T2 Bar<T, T2>(T t)
{
return default(T2);
}
static IList<T2> Bar<T, T2>(T t)
{
return new List<T2>();
}
此代码将导致类型“程序”已定义具有相同参数类型的名为“ Bar”的成员错误
这是一个完整的代码段,没有任何异步/等待:
static T2 Foo<T, T2>(Func<T, T2> d1)
{
return d1(default(T));
}
static IList<T2> Foo<T, T2>(Func<T, IList<T2>> d2)
{
return d2(default(T));
}
static IList<T2> Bar<T, T2>(T t)
{
Console.Write($"Bar: {typeof(T).Name} -> {typeof(T2).Name}: '{default(T)}' -> '{default(T2)}'");
return new List<T2>();
}
static void Main(string[] args)
{
//Error: The call is ambiguous between the following methods or properties: 'Program.Foo<T, T2>(Func<T, T2>)' and 'Program.Foo<T, T2>(Func<T, IList<T2>>)'
//Foo<string, int>(Bar<string, int>);
//Prints: Bar: String -> Int32: '' -> '0'
Foo<string, int>(d2: Bar<string, int>);
Console.ReadLine();
}