2013-03-29 128 views
6

我已经搜索了一些关于类型推断的内容,但似乎无法将任何解决方案应用于我的特定问题。嵌套泛型函数的类型推断

我正在做大量的构建和传递函数的工作。在我看来,它应该能够推断int类型。我能想到的唯一的事情是,类型推断算法不检查lambda返回类型。我已经剥夺了不必要的逻辑来更清楚地表明问题。

Func<T> Test<T>(Func<Func<T>> func) 
{ 
    return func(); 
} 

此编译:

Func<int> x = Test<int>(() => 
    { 
     int i = 0; 
     return() => i; 
    }); 

但这给出了错误“的方法类型参数不能从使用推断尝试显式指定类型参数。”:

Func<int> x = Test(() => 
    { 
     int i = 0; 
     return() => i; 
    }); 

我想我只想知道它为什么以这种方式和任何解决方法。

+0

非常相似的问题,但不完全相同http://stackoverflow.com/questions/6090159/inferring-generic-types-with-functional-composition –

回答

7

我要说的是,正确答案的问题是由E.Lippert在SO Why can't an anonymous method be assigned to var?

给出,但让我们用你的例子有点玩:

Func<Func<int>> f =() => 
{ 
    int i = 0; 
    return() => i; 
}; 

Func<int> x = Test(f); //it compiles OK 

与类型推断没有问题的Func<T> Test<T>(Func<Func<T>> func)在这里。 问题隐藏在你使用的匿名lambda表达式中,其类型无法推断。试试这个:

var f =() => 
{ 
    int i = 0; 
    return() => i; 
}; 

它给Compiler Error CS0815,说

不能lambda表达式分配给一个隐式类型的局部变量

和解释是:

的表达式用作隐式类型的初始化程序 变量必须有一个类型。因为匿名函数表达式,方法组表达式和空文字表达式不具有 类型,所以它们不是合适的初始值设定项。隐式类型 变量在其声明 中不能用空值初始化,尽管稍后可以赋值为null。

现在让我们尝试另一件事:

var x = Test(() => 
{ 
    Func<int> f =() => 0; 
    return f; 
}); 

它编译为好。因此,与原来的例子中,问题其实是与这条线:

return() => i; 

我们可以更进一步,根据什么埃里克利珀说,在他的回答提供了另一种功能来包装这个:

static Func<T> GetFunc<T>(Func<T> f) { return f; } 

现在我们可以重写你的代码,如:

var x = Test(() => 
{ 
    int i = 0; 
    return GetFunc(() => i); 
}); 

它也适用。

然而,据我所知,这一切都是开销,你应该只提供一个明确的类型。虽然这些解决方法是合适的,但当您需要使用lambda时,会返回匿名类型的对象。