仅对lambda表达式的隐式类型推断?为什么?困惑!
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了仅对lambda表达式的隐式类型推断?为什么?困惑!相关的知识,希望对你有一定的参考价值。
我有以下示例代码(仅用于C#3.5学习目的!)。
我正在调用接受IEnumerable和sort函数的Sort函数。如果我使用lambda表达式调用它(案例A),编译器可以派生返回类型TResult,但是当我传递func SortInt(案例B)时,编译器会抛出错误!
我无法理解为什么编译器在第二种情况下无法派生TResult!我似乎传递了完全相同的信息。或者这不准确?
请帮忙 !
int[] intArray = { 1, 3, 2, 5, 1 };
IEnumerable<int> intArray2 = Sort(intArray, x => SortInt(x)); // <= CASE A - OK !
IEnumerable<int> nextIntArray = Sort(intArray, SortInt); // <= CASE B - Compile Error: Cannot Infer Type !
public static IEnumerable<TResult> Sort<T, TResult>(IEnumerable<T> toBeSorted,
Func<IEnumerable<T>, IEnumerable<TResult>> sortFunc)
{
return sortFunc(toBeSorted);
}
public static IEnumerable<int> SortInt(IEnumerable<int> array)
{
return array.OrderByDescending(x => x);
}
看起来好像第二个示例中的推理失败,因为编译器无法对SortInt执行重载解析。
这可能是一个更全面的解释:
我同意类型推断不适用于方法组转换很烦人。我希望C#编译器在组中只有一个适用方法的常见情况下更聪明。但是,在复杂的情况下,最终会出现多个适用的重载,从而导致推断出不同的类型。
选项:
- 正如您所示,从lambda表达式中调用该方法
- 明确指定类型参数,而不是依赖于推理
- 将方法组强制转换为涉及的特定类型(比第二个选项更差)
- 使用单独的局部变量并明确指定其类型
基本上我会坚持使用前两个选项中的任何一个,因为它们都很烦人。请注意,第一个选项会有轻微的性能损失,因为它是一个额外的间接级别,但通常不会很重要。
IEnumerable<int> intArray = Sort(intArray, x => SortInt(x)); // <= CASE A - OK !
在本声明中,x => SortInt(x)
是一个代表表示如下:
delegate(IEnumerable<int> x){
return SortInt(x);
}
从技术上讲,你没有在声明的任何地方传递对SortInt
的任何引用。
Func,IEnumerable>是一个委托类型,它意味着它需要一个“指向函数的指针”,而不是函数。其他SortInt
是一种方法。
如果你甚至深入挖掘,你会发现x => SortInt(x)
的实际编译时表示如下:
private static IEnumerable<int> __XYZ(IEnumerable<int> x){
return SortInt(x);
}
private delegate IEnumerable<int> __XYZHANDLER(IEnumerable<int> x);
你的第1行将是
IEnumerable<int> intArray = Sort(intArray, new __XYZHANDLER(__XYZ) );
现在看你的第2行,SortInt
什么都没有,它是一个方法名,它不是任何类型或实例。方法参数只能有某种东西是某种类型的实例。 new Delegate是方法指针的实例,而不是任何方法。
qazxsw poi是以上所有解释的简短形式,lambda通常是一种较小的形式写匿名代表,编译器不会推断qazxsw poi到qazxsw poi。
您的代码有一些问题阻止它工作。
首先,你的类型并不都匹配。你传递一个int []作为IEnumerable,但是如果不调用.AsEnumerable()就不能这样做。
其次,T和TResult虽然在使用中是相同的,但是(int)与编译器不一样,但是你传入一个int数组并期望IEnumerable而不说结果的类型是什么。所以你必须传入你的版本的TResult类型(如Sort(intArray.AsEnumerable(),SortInt)),这是有效的,但你不需要TResult,因为你只是订购相同的类型,T。
所以,我摆脱了TResult并修复了类型:
x => SortInt(x)
我更喜欢上面的内容,但是,这是我可以获得的最接近您的样本,它可以工作:
SortInt
SortInt也可能是:
x => SortInt(x)
Akash给出了使用lambda表达式时存在差异的原因的解释。
以上是关于仅对lambda表达式的隐式类型推断?为什么?困惑!的主要内容,如果未能解决你的问题,请参考以下文章
KotlinKotlin 函数总结 ( 具名函数 | 匿名函数 | Lambda 表达式 | 闭包 | 内联函数 | 函数引用 )