C#编译器用于解析lambda表达式中的类型的规则是什么?
关于,我理解C#中不支持以下内容: 但是,我可以创建一个方法,C#编译器用于解析lambda表达式中的类型的规则是什么?,c#,C#,关于,我理解C#中不支持以下内容: 但是,我可以创建一个方法,Func,其形式如下: public static Func<T,T,T> Func<T>(Func<T,T,T> f) => f; 这也将被编译。因此,C#编译器似乎能够推断lambda的返回类型。但是,以下内容无法编译: var func = Func((x,y) => Math.Log(x) + Math.Log(y)); 因为编译器似乎无法从正文中使用的方式推断x和y的类型
Func
,其形式如下:
public static Func<T,T,T> Func<T>(Func<T,T,T> f) => f;
这也将被编译。因此,C#编译器似乎能够推断lambda的返回类型。但是,以下内容无法编译:
var func = Func((x,y) => Math.Log(x) + Math.Log(y));
因为编译器似乎无法从正文中使用的方式推断x
和y
的类型
那么,我的问题是:关于lambda表达式的类型推断的确定规则是什么;编译器会推断出什么,它不会推断出什么 您必须提供所有参数和结果的类型,或者:
- 显式地,通过在通用尖括号(
)之间或lambda参数列表中声明它(例如:
)(int a,int b)=>{/*…*/}
- 隐式地,在编译器可以推断结果类型的情况下,推断
类型的方式相同var
- 之所以编译,是因为这里提供的类型是
double
public static Func<T,T,T> Func<T>(Func<T,T,T> f) => f; var func = Func<double>((x,y) => Math.Log(x) + Math.Log(y));
- 但是,这不会编译,因为
和T1
的类型未知。编译器无法改变它们的类型的使用方式T2
public static Func<T1,T2,T3> Func<T1,T2,T3>(Func<T1,T2,T3> f) => f; var func = Func((x,y) => Math.Log(x) + Math.Log(y));
公共静态函数Func(Func f)=>f; var func=func((x,y)=>Math.Log(x)+Math.Log(y));
Dump
方法来描述类型推理引擎的状态。我用它来促进更快速的调试,并考虑对算法进行扩展。(其中一些仍在代码中,已注释掉。)
编译器会推断出什么,它不会推断出什么
这是一个过于宽泛的问题,无法给出明确的答案。但关于你问题中的例子,基本行动是:
- 类型参数的边界是从与形式参数类型匹配的普通参数推断出来的
- lambda,其中lambda的所有形式参数类型都是推断的或已知的,其返回类型是推断的
- 重复上一步,直到算法无法取得进展或推断出矛盾
我录制了一段视频——十年前的现在——一步一步地解释所有这些,但显然它已经不在MSDN上了。我很烦恼 我同意现在已经放弃的答案。。只需要阅读指定的参考资料,就可以知道c#匿名类型推理的确切规则,而且我承认我没有必要的知识来说明这个问题有多广泛,但我相信,我相信世卫组织说这是一个非常广泛的问题 然而,我本以为,如果规则是明确的,那么编译器应该工作,因为某些类型的推理规则是逻辑的,而不是任意的 在您的示例中,无法执行最后一次计算,因为每个参数的类型可以是“double”类型或其他兼容类型之外的所有类型,这是正确的。但是相反,如果你编写了lambda表达式,这样就不可能在返回类型函数的推理中出错,那么,我希望它能工作,而不是不工作 例如,下面的代码,我希望它可以工作,但不能:
public static Func<T1, T2, T3> Func<T1, T2, T3>(Func<T1, T2, T3> f) => f;
var func = Func((x, y) => string.Format("{0},{1}", x.ToString(), y.ToString()));
所以,在我看来,编译器完全避免进行任何类型的推理。当它是安全的,然后它执行计算,否则就不会
我希望我回答了你的问题,或者至少给出了一个有用的指示或跟踪。我投票决定结束,因为C#spec中包含的类型推断太宽泛了。如果你问为什么你的特定代码无法编译,那是一回事,但要求所有类型推断规则都太宽泛了。@DStanley,规范中的何处?
var func=func((双x,双y)=>$“{x+y}”)代码>-这不是在推断什么。它接受两个double并输出一个字符串,因此它的类型为Func
@DavidArno 7.5.2类型推断,因为它无法推断x
和y
的类型,因为它将编译多个类型。它不会为你选择一个。对于其他示例,参数没有类型推断,因为您明确地说类型是double
Perfect。谢谢Eric,可惜你的视频不见了;这听起来很值得一看。
var func = Func((x,y) => Math.Log(x) + Math.Log(y));
public static Func<T,T,T> Func<T>(Func<T,T,T> f) => f;
var func = Func<double>((x,y) => Math.Log(x) + Math.Log(y));
public static Func<T1,T2,T3> Func<T1,T2,T3>(Func<T1,T2,T3> f) => f;
var func = Func((double x, double y) => $"{x + y}");
public static Func<T1,T2,T3> Func<T1,T2,T3>(Func<T1,T2,T3> f) => f;
var func = Func((x,y) => Math.Log(x) + Math.Log(y));
public static Func<T1, T2, T3> Func<T1, T2, T3>(Func<T1, T2, T3> f) => f;
var func = Func((x, y) => string.Format("{0},{1}", x.ToString(), y.ToString()));
double x1 = 0, y1 = 0;
var func = Func((x, y) => Math.Log(double.TryParse(x.ToString(),x1)) + Math.Log(double.TryParse(y.ToString(), y1)));