2013-03-29 66 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時,會返回匿名類型的對象。