gpt4 book ai didi

将方法组作为委托(delegate)传递时,C# 调用不明确

转载 作者:太空狗 更新时间:2023-10-29 21:33:10 26 4
gpt4 key购买 nike

希望有人能给我解释一下。对不起,如果它是重复的,解释我所看到的内容的关键字现在超出了我的范围..

这里是一些编译的代码

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));
}
}

这里是一些没有的代码

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;
}
}

通过添加构造函数重载,这显然会产生歧义,但我不确定为什么。 Math.Sqrt 没有重载,显然返回类型为 double,而不是 Task

这里是错误:

The call is ambiguous between the following methods or properties: 'ConsoleApplication1.Transformer<double,double>.Transformer(System.Func<double,double>)' and 'ConsoleApplication1.Transformer<double,double>.Transformer(System.Func<double,System.Threading.Tasks.Task<double>>)'

有人可以解释为什么这个选择对编译器来说不是显而易见的吗?


为那些关心的人提供简单的解决方法:

class Program
{
static void Main(string[] args)
{
new Transformer<double, double>(d => Math.Sqrt(d));
}
}

最佳答案

您对 Func<Tin, Tout> 的理解方式有轻微的误解作品。看看the docs :

public delegate TResult Func<in T, out TResult>(
T arg
)

第一个参数是参数,最后一个参数是返回类型。

当您查看这个简化版本的代码时:

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)
{
}
}

您会注意到两个参数都首先指定了 double ,这是一个参数,然后返回类型不同:T对比Task<T> .

然而,我们都知道:重载是根据方法名称、参数数量和参数类型完成的。返回类型被完全忽略。在我们的例子中,这意味着我们有两个 Func<Tin, Tout>double作为参数和 T对比Task<T>作为返回类型。

围绕编译切换参数就好了:

internal class MyClass<T, U>
{
public MyClass(Func<T, U> arg)
{
}

public MyClass(Func<Task<T>, U> arg)
{
}
}

如果您在 Visual Studio 中查看,您会注意到此方法现在变灰了,这是有道理的,因为 Method 的参数类型为 double因此将始终匹配 T而不是 Task<T> .

因此,为了测试如果您传入一个不同的异步方法它现在会命中正确的重载,您可以添加第二个方法:

private static double MethodAsync(Task<double> d)
{
throw new NotImplementedException();
}

并使用

调用它
new MyClass<double, double>(MethodAsync);

您现在会注意到异步 Func<Task<T>, U>>被击中(您可以通过简单地从构造函数打印到控制台来验证)。


简而言之:您正在尝试对返回类型执行重载决策,这显然是不可能的。

关于将方法组作为委托(delegate)传递时,C# 调用不明确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31994817/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com