2016-07-05 194 views
1

我一直認爲匿名函數和命名函數一樣強大,直到我想將一個私有命名函數變成一個匿名函數,因爲只有一個方法體需要調用這個函數。一個簡單的例子:匿名函數與非匿名函數一樣強大

public void Init(List<int> numbers, List<string> texts) 
{ 
    int n = GetFirst(numbers); 
    string t = GetFirst(texts); 
} 

private T GetFirst<T>(List<T> list) 
{ 
    return list[0]; 
} 

期望是定義像

GenFunc<T, List<T>, T> getFirst = list => list[0]; 

和使用的東西,而不是實例方法GetFirst說。使用Func是不可能的,因爲泛型參數具有不同的語義。因此,我所定義的委託(的Func「鹼基」)

delegate T GetFirstDelegate<T>(List<T> list); 

但我只能與定義的通用參數例如實例化

GetFirstDelegate<string> getFirst = list => list[0]; 

,但不是因爲我希望與佔位符泛型參數:

GetFirstDelegate<T> getFirst = list => list[0]; 

這讓我覺得,匿名方法並不像mightly的命名方法 - 至少在一般的使用方面 - 或很我錯過了什麼?

+0

當然,對於您的例如,LINQ已經爲IEnumer定義了一個'.First()'能夠' –

回答

1

什麼你實際上是試圖做的是創造一個一般變量

Func<List<T>, T> getFirst<T> = list => list[0]; 

但不幸的是,這是無效C#作爲變量不能通用。只有類型(接口,類,結構),委託和方法可以是通用的。

2

看着this的問題,你可以看到泛型匿名函數在C#中是不可能的。成像時編譯器必須處理常規的泛型方法。它實際上爲它所要求的每種類型生成一個重載(至少是簡單的)。當你用泛型參數聲明一個變量時,編譯器在這種情況下應該怎麼做?它不能用不同的通用參數生成新的變量。

希望這是明確的。你基本上只需要知道泛型方法和類是編譯時的東西!

0

接受List<T>作爲輸入並返回T的函數的簽名是Func<List<T>, T>而不是Func<T, List<T>, T>

我想這是你想要的東西:

private Func<List<T>, T> GenGetFirst<T>() 
{ 
    return list => list[0]; 
} 

用法:

public void Init(List<int> numbers, List<string> texts) 
{ 
    int n = GenGetFirst<int>()(numbers); 
    string t = GenGetFirst<string>()(texts); 
} 

或者更明確方式:

public void Init(List<int> numbers, List<string> texts) 
{ 
    Func<List<int>, int> intFunc = GenGetFirst<int>(); 
    Func<List<string>, string> stringFunc = GenGetFirst<string>(); 

    int n = intFunc(numbers); 
    string t = stringFunc(texts); 
} 
+0

我很感謝你的回答,但我想擺脫命名的方法,並用C#中不可能的匿名函數來表達它,就像我剛學過的那樣。 – David