1

После просмотра ответа, в котором указано, как перечислять индексы с использованием коллекции с использованием Linq, я решил написать метод расширения WhereWithIndex, который ведет себя аналогично Where, но функция ввода должна иметь два аргумента, элемент и индекс.C#, записывающий подпись типа для `WhereWithIndex`

Пример использования должно быть:

names = new String[] {"Bob", "Alice", "Luke", "Carol"} 
names.WhereWithIndex((_, index) => index % 2 == 0) // -> {"Bob", "Luke"} 

Я смог встроить эту логику в моей программе, это выглядит следующим образом:

iterable 
    .Select((item, index) => new {item, index}) 
    .Where(x => condition(item, index)) 
    .Select(x => x.item); 

Но тип подписи я должен дать этому расширению метод все еще ускользает от меня. Я пробовал:

public static IEnumerable<T> WhereWithIndex(this IEnumerable<T> iterable, Predicate<T, int> condition) { 

Потому что я хочу в качестве входных данных перечислимого чего-либо я не мог пометить его int или String поэтому я попытался с помощью T для обозначения общности following the official documentation, условие предиката, так что я сказал так. Как выразить тип делегата с двумя аргументами, который ускользает от меня, я попытался использовать запятую для разделения аргументов, но я просто догадываюсь, как I could only fund examples of predicates with only one input.

Это дает мне ошибку:

Example.cs(22,29): error CS0246: The type or namespace name `T' could  
not be found. Are you missing an assembly reference? 

Любая идея о написании этого типа подписи? Если это проще в версии C# 6, было бы неплохо также упомянуть об этом.

+1

btw, 'Where' имеет перегрузку с индексом: https://msdn.microsoft.com/en-us/library/bb549418(v=vs.110).aspx; в отношении вашей проблемы: введите общий метод: 'WhereWithIndex ', если он вам еще нужен – ASh

+0

Вы пропустили 'T' после имени метода:' ... WhereWithIndex (...) '. – Dennis

ответ

3

already exists версия Where это делает. Он имеет эту подпись:

public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate); 

Единственное ваша подпись отсутствовала была <TSource> рядом с Where. Это говорит компилятору, что функция является общей. Плюс с использованием Func<TSource, int, bool> вместо Predicate<T, int>. В C#, Func<P1, P2, P3, R> это функция, которая принимает P1, P2, P3 и возвращает R, такие как:

public R MyFunction(P1 p1, P2 p2, P3 p3) { ... } 

С другой стороны, Action<P1, P2> является функцией, которые принимают P1 и P2 и не возвращает ничего:

public void MyAction(P1 p1, P2 p2) { ... } 

Обратите внимание, что в этих образцах, MyFunction и MyAction не дженерики (P1..P3 и R должны быть фактические типы). Если вы хотите, чтобы сделать его универсальным, вы бы изменить его на:

public void MyAction<P1, P2>(P1 p1, P2 p2) { ... } 

В этом случае, P1 и P2 являются имена переменных произвольного типа.

+0

Почему вы используете 'TSource' над' T'? – Caridorc

+0

И почему 'Function' с возвратом типа' bool' вместо 'Predicate'? Это новая функция? – Caridorc

+1

Это просто имя переменной типа, представляющее тип 'IEnumerable'. Это может быть что угодно. – Juan