希望有人可以向我解释这一点.对不起,如果这是重复的话,解释我所看到的内容的关键词现在已超出我的范围了.
这里有一些编译的代码
class Program
{
static void Main(string[] args)
{
new Transformer<double, double>(Math.Sqrt);
}
}
class Transformer<Tin, Tout>
{
Func<Tin, Task<Tout>> actor;
public Transformer(Func<Tin, Tout> actor)
{
this.actor = input => Task.Run<Tout>(() => actor(input));
}
}
Run Code Online (Sandbox Code Playgroud)
这里有一些代码没有
class Program
{
static void Main(string[] args)
{
new Transformer<double, double>(Math.Sqrt);
}
}
public class Transformer<Tin, Tout>
{
Func<Tin, Task<Tout>> actor;
public Transformer(Func<Tin, Tout> actor)
{
this.actor = input => Task.Run<Tout>(() => actor(input));
}
public Transformer(Func<Tin, Task<Tout>> actor)
{
this.actor = actor;
}
}
Run Code Online (Sandbox Code Playgroud)
通过添加构造函数重载,这显然会产生歧义,但我不确定为什么.Math.Sqrt没有重载,显然返回类型为double,而不是Task <double>.
这是错误:
以下方法或属性之间的调用不明确:'ConsoleApplication1.Transformer <double,double> .Transformer(System.Func <double,double>)'和'ConsoleApplication1.Transformer <double,double> .Transformer(System.Func <双,System.Threading.Tasks.Task <双>>)"
有人可以解释为什么选择对编译器来说不明显吗?
易于解决的问题:
class Program
{
static void Main(string[] args)
{
new Transformer<double, double>(d => Math.Sqrt(d));
}
}
Run Code Online (Sandbox Code Playgroud)
你对如何Func<Tin, Tout>运作有轻微的误解.看看文档:
public delegate TResult Func<in T, out TResult>(
T arg
)
Run Code Online (Sandbox Code Playgroud)
第一个参数是参数,最后一个参数是返回类型.
当您查看代码的简化版本时:
internal class Program
{
public static void Main(string[] args)
{
new MyClass<double, double>(Method);
}
private static double Method(double d)
{
throw new NotImplementedException();
}
}
internal class MyClass<T, U>
{
public MyClass(Func<U, T> arg)
{
}
public MyClass(Func<U, Task<T>> arg)
{
}
}
Run Code Online (Sandbox Code Playgroud)
你会注意到两个参数首先指定double,这是一个参数,然后在返回类型上有所不同:Tvs Task<T>.
但是我们都知道:重载是基于方法名称,参数arity和参数类型完成的.返回类型完全被忽略.在我们的例子中,这意味着我们有两个Func<Tin, Tout>与double作为参数和TVS Task<T>的返回类型.
切换参数编译就好了:
internal class MyClass<T, U>
{
public MyClass(Func<T, U> arg)
{
}
public MyClass(Func<Task<T>, U> arg)
{
}
}
Run Code Online (Sandbox Code Playgroud)
如果您将在Visual Studio中查看,您会注意到此方法现在变为灰色,这是有道理的,因为参数Method是类型的double,因此总是匹配T而不是Task<T>.
因此,为了测试它是否会在传递不同的异步方法时达到正确的重载,您可以添加第二种方法:
private static double MethodAsync(Task<double> d)
{
throw new NotImplementedException();
}
Run Code Online (Sandbox Code Playgroud)
并使用它来调用它
new MyClass<double, double>(MethodAsync);
Run Code Online (Sandbox Code Playgroud)
您现在将注意到异步Func<Task<T>, U>>被命中(您可以通过从构造函数中简单地打印到控制台来验证).
简而言之:您尝试在返回类型上执行重载解析,这显然是不可能的.