IEnumerable Select

#c# #linq

#c# #linq

Вопрос:

Может кто-нибудь объяснить, почему следующая строка C # не ведет себя так же, как следующий каждый блок?

 string [] strs = {"asdf", "asd2", "asdf2"};
strs.Select(str => doSomething(str));


foreach(string str in strs){
  doSomething(str);
}
  

Я помещаю точку останова внутри doSomething(), и она не срабатывает при выборе, но это происходит с foreach .

TIA

Комментарии:

1. Вы должны прочитать первые несколько слов раздела примечания в документации .

2. @ChaosPandion Ваш первоначальный комментарий был намного лучше. 😉

3. @Marc — Я хотел быть немного более дипломатичным, поскольку OP может не знать, что означает отложенное или выполнение.

4. @ChaosPandion на самом деле проблема заключается не столько в отложенном выполнении, сколько в том, что он никогда не использует результат своей операции.

5. @ChaosPandion: я предполагаю, что ваше первоначальное утверждение было RTFM 😉 Я прочитал запись MSDN для IEnumerable. Выберите, но не удалось прочитать замечания. Теперь я это вижу. Я понимаю отложенное выполнение. Спасибо за указатель.

Ответ №1:

Это связано с тем, что запросы LINQ откладываются. Лямбда-выражение, переданное Select методу, фактически выполняется при доступе к результату.

Попробуйте:

 string [] strs = {"asdf", "asd2", "asdf2"};
var result = strs.Select(str => doSomething(str));

foreach(var item in result) {
}
  

Комментарии:

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

Ответ №2:

Linq Запрос не будет обработан, пока вы не преобразуете его в Enumarable using ToList() , ToArray() , и т.д.

И, кстати, эквивалент вашего foreach утверждения выглядит примерно так:

строки.ForEach(doSomething);

 strs.ToList().ForEach(doSomething);
  

или

 Array.ForEach(strs, doSomething);
  

Комментарии:

1. Я предполагаю, что вы имеете в виду массив. ForEach(str, doSomething)

2. @dharga, да, это правильно, я обычно делаю ошибки, когда пишу код без тестирования, правильная версия будет либо strs.ToList().ForEach(doSomething); или Array.ForEach(strs, doSomething);

3. .Select() является ленивым. Кроме того, doSomething() должен возвращать значение, поскольку .Select принимает a (a -> b), или, говоря языком .NET, он принимает функцию<..>, а не действие <..> .

Ответ №3:

вам нужно будет сделать что-то вроде

 string [] strs = {"asdf", "asd2", "asdf2"};
strs = strs.Select(str => doSomething(str)).ToArray();


foreach(string str in strs){
  doSomething(str);
}
  

Ответ №4:

Я думаю, как только вы используете значения, возвращенные из select, вы увидите вызов doSomething() . Проверьте yield, чтобы понять, почему это происходит.