2012-05-16 2 views
1

У меня есть ForEachWithIndex EMКак создать метод For_Each_With_Condition_With_Index расширения (EM)

static void ForEachWithIndex<T>(this IEnumerable<T> enu, Action<T, int> action) 
{ 
    int i = 0; 
    foreach(T item in enu) 
     action(item, i++); 
} 

Я называю это, как этот

my_int_array.ForEachWithIndex((x, i) => x += i); 

Теперь я хочу, чтобы создать одну, которая проверяет условия, а затем выполнить это действие.

Обычно я использую выше как

my_int_array.ForEachWithIndex((x,i) => 
{ 
    if (x != 0) 
     x += i; 
}); 

Я хочу EM, который принимает это условие в качестве параметра также. Как это сделать?

+0

Вы можете добавить предикат к своему расширению – Ation

+0

Да, именно это. Как? –

ответ

0

Вам необходимо пройти дополнительный параметр Func, что-то вроде этого:

public static void ForEachWithIndex<T>(this IEnumerable<T> enu, 
          Action<T, int> action, Func<T, int, bool> condition) 
{ 
    int i = 0; 
    foreach (T item in enu) 
    { 
     if (condition(item, i)) 
     { 
      action(item, i); 
     } 
     ++i; 
    } 
} 

И это пример кода для вашего примера:

my_int_array.ForEachWithIndex((x, i) => x += i, (x, i) => x != 0); 
+0

Вы мой человек ... Спасибо –

+1

@Santo: «i» - тип значения. Предикаты могут изменять только ** копию ** «i», а не оригинальное значение !. – Dennis

+0

Деннис, вы правы Я думал о случае, когда анонимный предикат объявлен, а локальная переменная используется внутри предиката. – Alan

3

Я постараюсь избежать создания одного большого метода расширения, который сделает все это. Разбейте его, как и LINQ.

Лично я не стал бы на самом деле любой из этого, хотя - я бы построить запрос с помощью LINQ, а затем использовать foreach заявление для действия:

// Assuming you want the *original* indexes 
var query = array.Select((Value, Index) => new { value, Index }) 
       .Where(pair => pair.Index != 0); 

foreach (var pair in query) 
{ 
    // Do something 
} 

Трудно точно знать, что вы «пытаюсь сделать это, учитывая, что приращение параметра лямбда ничего не достигнет. I : настоятельно рекомендую вам подумать о создании блоков, хотя ... и вы можете найти Eric Lippert's views on foreach vs ForEach интересным.

+0

Я лично отражаю ваши чувства, не создавая одну большую ЭМ. Но я не могу с этим поделать. Мне предоставлен модуль для разработки. В нем даже после использования EM модули моего модуля меняются с каждым днем. Что произойдет, если я не буду использовать EM. –

+0

@NikhilAgrawal: у вас будет более простой в обслуживании код, потому что вы логически отделите условие от действия? –

1

Просто добавьте условие делегата к списку параметров:

static void ForEachWithIndexWithCondition<T>(this IEnumerable<T> enu, 
        Func<T, int, bool> condition, Action<T, int> action) 
{ 
    int i = 0; 
    foreach (T item in enu) 
    { 
     if (condition(item, i)) 
      action(item, i); 
     i++; 
    } 
} 

Использование:

 var list = new List<string> { "Jonh", "Mary", "Alice", "Peter" }; 

     list.ForEachWithIndexWithCondition(
      (s, i) => i % 2 == 0, 
      (s, i) => Console.WriteLine(s)); 
+1

Деннис Я думаю, что 'i' должен быть увеличен за пределами действия. Иначе это даст неправильные индексы. и BTW, как это назвать? –

+0

@NikhilAgrawal, да, вы правы - в случае, если условие ложно, следующая итерация даст неправильные индексы. Обновлен ответ. – Dennis

+0

Без использования это был полупеченный ответ. Если бы использование было дано до того, как я принял бы ваш ответ. Еще спасибо. +1 от меня. –

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