2016-07-05 2 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]; 

Это заставляет меня думать, что анонимные методы не столь могучую, как названные методы - по крайней мере, с точки зрения общего пользования - или я Я чего-то не хватает?

+0

Конечно, для вашего Например, LINQ уже определяет '.First()' для 'IEnumer способный ' –

ответ

1

То, что вы на самом деле пытаетесь сделать, это создать общую переменную как то

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

Но к сожалению, это не действует C#, как переменные не могут быть общими. Только типы (интерфейсы, классы, структуры), делегаты и методы могут быть общими.

2

В вопросе this вы можете видеть, что общие анонимные функции невозможны в C#. Отображение, когда компилятор должен использовать обычный общий метод. Он фактически генерирует перегруз для каждого типа, к которому он был вызван (по крайней мере упрощенно). Когда вы объявляете переменную с общим параметром, как должен компилятор делать в этом случае? Он не может генерировать новые переменные с разными родовыми параметрами.

Надеюсь, это ясно. Вы просто должны знать, что общие методы и классы - это время компиляции!

0

Подпись для функции, которая принимает List<T> как вход и возврат T is 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

Смежные вопросы