#c# #linq #resharper
#c# #linq #перетачиватель
Вопрос:
У меня есть такой код, как этот:
Person FirstPerson = personsEnumerable .Первый ();
, где personsEnumerable
IEnumerable<Person>
Теперь Resharper подчеркивает переменную personsEnumerable и говорит «Возможная итерация IEnumerable». Я понимаю, что означает это предупреждение из других вопросов здесь, на SO, но мне интересно, почему оно показывает это в моем примере? Я думаю, что First() возвращает первый элемент, и нет необходимости повторять коллекцию вообще?
Является ли это «общим» предупреждающим сообщением, которое неприменимо в моем случае (и я могу его проигнорировать), или я не понимаю, как на самом деле работает First() ?
Комментарии:
1. «Я думаю, что First() возвращает первый элемент, и нет необходимости повторять коллекцию вообще» Даже если вам нужен только первый, запрос должен быть выполнен. Тем не менее, я предполагаю, что вы обращаетесь
personsEnumerable
к нему несколько раз.2. Покажите нам остальную часть кода. Вы повторяете последовательность дважды, что может означать избыточный поиск данных.
Ответ №1:
Да, он возвращает первый элемент, но все равно создает перечислитель для получения этого первого элемента.Вы могли бы добавить ToArray
или ToList
после Where
, чтобы предотвратить это. Однако, если вы хотите просто получить первый элемент, вы можете использовать перегруженную версию First
, для которой требуется Func
делегат, и вы можете удалить Where
.
Ответ №2:
Рассмотрим этот код:
var personsEnumerable = peopleList.OrderBy(p => p.Age);
var firstPerson = personsEnumerable.First();
foreach (var p in personsEnumerable)
{
// whatever
}
Первая строка кода настраивает порядок сортировки списка и создания результатов, но на самом деле она ничего не делает, пока вы не попытаетесь ее перечислить. Вторая строка кода, то в конечном итоге будет выполнена сортировка. Таким образом, хотя вы не перечисляете весь результат целиком, вы выполняете код для получения результата. И в некотором роде это повлекло бы за собой выполнение всей тяжелой работы.
foreach
Цикл снова выполнит сортировку, прежде чем фактически перечислит результаты.
Комментарии:
1. интересно, является ли personsEnumerable . Any() также будет выполнять сортировку?
2. @GregorValentin: Да.
3. спасибо, приятно это знать! из msdn: «Перечисление источника прекращается, как только результат может быть определен». Так что, имо, в этом случае вы можете проигнорировать предупреждение.
4. @GregorValentin: Вы, вероятно, не захотите игнорировать это предупреждение. В приведенном выше случае, если вы заменили
First()
наAny()
, вызовAny()
повлечет за собой стоимость сортировки. И то же самое сделал бы тотforeach
. Не проблема, если в нем всего несколько элементов, но еслиpeopleList
в нем миллион элементов, вы определенно заметите разницу.5. Спасибо за обсуждение. Очень полезно!