我有一个有两个重载的方法
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
由于异步/等待的性质,它会展开任务并使我的Bar
等同于
T2 Bar(T input)
要使其正常工作,我必须显式地将//3
转换为
Foo((Func<T,Task<T2>>)Bar);
有没有什么优雅的方法来避免这种显式的类型转换?
更新以阐明Foo的用途
Foo()不是调用委托的方法。它注册委托,委托将由不同的机制调用。Foo()没有type参数的原因是因为type参数是在类级别声明的。
完整的模型代码可以在这里找到https://dotnetfiddle.net/c6UCpi
发布于 2018-08-02 05:53:54
我找到了一个非常好的解决方案:命名参数。
不是调用
Foo(Bar);
我应该使用在操作中声明的显式命名参数来调用它。
Foo(asyncDelegate: Bar);
这显式地告诉编译器使用异步重载,避免在没有显式强制转换的情况下产生歧义。
查看此以获取完整代码片段https://dotnetfiddle.net/c6UCpi
发布于 2018-08-02 09:16:36
您面临的问题不是关于async/await,而是关于具有签名的方法,只是返回类型不同。
这可以用这个简单的例子来演示:
static T2 Bar<T, T2>(T t)
{
return default(T2);
}
static IList<T2> Bar<T, T2>(T t)
{
return new List<T2>();
}
此代码将导致类型'Program‘已经定义了具有相同参数类型的名为'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();
}
https://stackoverflow.com/questions/51642713
复制相似问题