类型推断不起作用
本文关键字:不起作用 类型 | 更新日期: 2023-09-27 18:19:27
class Sample
{
public static T M<T, TParam1>(TParam1 param1)
{
return default(T);
}
}
class Program
{
static void Main(string[] args)
{
double d = Sample.M((int)121);
}
}
此代码不会编译并导致以下错误消息:
方法的类型参数 "ThreadPoolTest.Sample.M(TParam1("不能从 用法。尝试指定类型参数 明确地
为什么类型推断在此示例中不起作用?
类型推断只能使用方法调用的参数。就类型推断而言,将结果分配给double
这一事实完全无关紧要。换句话说,就编译器而言,它需要弄清楚这意味着什么:
Sample.M((int) 121)
没有任何更多信息。例如,你可以说Sample.M<int, int>
,或Sample.M<double, int>
,或Sample.M<string, int>
- 没有信息,所以说出其中哪一个是更好的匹配。
您没有在参数列表中提及T
,因此类型推断无济于事。
乔恩的回答当然是正确的。考虑一下为什么 C# 在进行推理时不考虑"返回类型"是很有启发性的。此处的基本原则是,在分析表达式时,类型信息从内部流向外部,而不是从外部流向内部。
在您的特定情况下,预期的返回类型是什么非常明显,因为您正在分配给明确双精度的东西。但是在很多情况下,它根本不明显:
static R M<A, R>(A a) { return default(R); }
static void N(int x, double y) {}
static void N(double x, int y) {}
...
N(M(123), 456);
好吧,现在怎么办?如果关于"分配给什么"的类型信息必须流入 M 上的类型推断,那么必须流入的类型信息是"它可以是 int 或 double"。
但是等等,这是对的吗?我们可以在这里对可能的返回类型进行更合乎逻辑的推断。
如果它是 int,那么我们有N(M<int, int>(123), 456)
,N 上的重载解析将失败,因为该调用是不明确的;它可能是 N 的任一版本!
因此它不可能是 int,对吧?它必须是双精度的,因为这意味着调用N(M<int, double>(123), 456)
这无疑是第二个重载。
现在想象一下,对 Q(R(S(N(M(...每个都有十几个超载,也许还有一些 lambda 扔进去。分析变得异常复杂;很难正确实现,用户很难理解他们的程序做什么,为什么会产生错误以及如何修复它们。
简单地说,表达式的类型分析必须根据其内容而不是上下文来确定要容易得多。这就是我们所做的。您向编译器抛出的重载解决问题必须在不查看问题上下文的情况下解决;我们只看参数列表的内容来解决问题,参数列表中没有足够的信息。
现在,lambdas是这里的例外。Lambda 参数类型是从其上下文推断出来的,因此,您可以轻松地强制编译器为深度嵌套的 lambda 尝试数万亿种可能的类型赋值,以解决重载解析问题。但我们不想将分析 lambda 的困难扩展到整个语言;我们希望将这些困难狭隘地限制在需要它们的特定语言功能上。
因为您没有指定返回类型。
以下是您想要的:
double d = Sample.M<double, int>((int)121);