Я пытаюсь понять, какое влияние оказывает AsEnumerable()
на мои данные при итерации по ним. У меня есть фиктивный список в памяти. Если я foreach
завершу первый вызов ToList()
, это вызовет оценку, и моя распечатка будет выглядеть следующим образом (см. Код внизу этого поста, чтобы объяснить вывод):
entering da
yield return
yield return
yield return
exiting da
doing something to aaron
doing something to jeremy
doing something to brendan
Все имеет смысл. ToList()
заставляет выходы в хранилище сначала выполняться в списке, затем мы получаем нашу итерацию foreach
. Пока все хорошо.
Когда я делаю то же самое, за исключением использования AsEnumerable()
, основываясь на том, что я прочитал относительно IQueryable
(я понимаю, что это не IQueryable
), я бы подумал, что это также вызывает оценку, но это не так , Это выглядит так:
entering da
yield return
doing something to aaron
yield return
doing something to jeremy
yield return
doing something to brendan
exiting da
Как если бы я даже не позвонил AsEnumerable()
, поэтому мой вопрос:
Почему AsEnumerable
ведет себя иначе для коллекции в памяти по сравнению с linq to sql и типом возврата IQueryable
?
Как все это изменится, когда мой репозиторий изменится на использование SqlDataReader
и выполнение yield return
внутри считывателя (при вызове Read()
метода). Будут ли строки, поступающие из SqlServer, которые буферизованы в сетевом буфере клиента, полностью проанализированы перед выполнением foreach
(обычно здесь yield
вызывает «паузу» в репо, пока каждая строка обрабатывается блоком foreach
Я знаю, что если в этом случае я сначала позвоню ToList()
, я смогу принудительно оценить SqlDataReader
, поэтому делает ли AsEnumerable
то же самое здесь?
Примечание: меня не интересует, хорошая ли идея ввода yield в SqlDataReader
, поскольку он может держать соединение открытым, я уже забил эту тему до смерти:)
Вот мой тестовый код:
public class TestClient
{
public void Execute()
{
var data = MockRepo.GetData();
foreach (var p in data.AsEnumerable()) //or .ToList()
{
Console.WriteLine("doing something to {0}", p.Name);
}
Console.ReadKey();
}
}
public class Person
{
public Person(string name)
{
Name = name;
}
public string Name { get; set; }
}
public class MockRepo
{
private static readonly List<Person> items = new List<Person>(3)
{
new Person("aaron"),
new Person("jeremy"),
new Person("brendan")
};
public static IEnumerable<Person> GetData()
{
Console.WriteLine("entering da");
var enumerator = items.GetEnumerator();
while (enumerator.MoveNext())
{
Console.WriteLine("yield return");
yield return enumerator.Current;
}
Console.WriteLine("exiting da");
}
}