Linq c#, особенности работы с IEnumerable<T>-ами

430
01 сентября 2017, 20:48

Простите, боюсь, не получится четко сформулировать вопрос и показать пример кода.

Ситуация:

Когда-то у меня было такое, что метод возвращал IEnumerable<T>, при этом, в какой-то момент при переборе элементов с помощью foreach оказывалось, что элементов там уже не было (как бы IEnumerable<T> пустой). И это при том, что изначально метод возвращал не пустой список.

//Допустим, метод GetElements() возвращает не пустой IEnumerable<Element>
var elements = SomeStaticClass.GetElements();
//затем не помню что происходит
//в итоге
foreach (var element in elements)
{
    //сюда не разу не зашли
}

То есть в каких-то случаях IEnumerable<T> оказывался просто перечислителем, уже без данных.

Однако если вначале сделать GetElements().ToArray(), то такой проблемы уже не наблюдалось.

//Допустим, метод GetElements() возвращает не пустой IEnumerable<Element>
var elements = SomeStaticClass.GetElements().ToArray(); //!!!!!
//затем не помню что происходит
//в итоге
foreach (var element in elements)
{
    //сюда зашли много раз
}

Вопрос:

В каких случаях так происходит? Это полезно знать, чтобы не плодить каждый раз ToArray(), даже когда не надо.

Answer 1

Есть два способа выполнения запроса LINQ: отложенное и немедленное выполнение.
При отложенном выполнении LINQ-выражение не выполняется, пока не будет произведена итерация или перебор по выборке.
Если точнее когда linq запрос возвращает IEnumerable ,эти запросы называется "отложенное". отложенный запрос, который в конечном итоге возвращает IEnumerable, может перечисляться снова и снова, получая последние данные из источника. В этом случае не нужно ни вызывать, ни объявлять запрос заново.То есть выполнение запроса после его создания откладывается. Само получение результатов производится при переборе в цикле foreach.
Методы ToList,ToArray,ToXXX и которые возвращают одно атомарное значение или один элемент называется "немедленным".
Эти методы немедленно выполняется

    //Example
    List<string> persons =new List<string> { "Larson", "Jonny", "Fredy", "Michael","Lanny" };
    //это отложенный запрос.до foreach мы можем изменить эти данные
    //на данный момент у нас ест 2 значение в result-e
    IEnumerable<string> result = persons.Where(x => x.StartsWith("L"));

    // удалил один значений из листа.
    //это влияет и на наш result!!!!
    persons.Remove("Lanny");
    //на данный момент у нас ест 1 значение в result-e
    foreach (string s in result)
    {
        Console.WriteLine(s);
    }
READ ALSO
Awesomium многопоточность

Awesomium многопоточность

Работаю с Telegram APi от MrRound Robin и Awesomium

451
Есть ли право на запись файла?

Есть ли право на запись файла?

Есть файл, точнее - его полный путь к файлуМожно ли узнать, есть ли право на запись файла?

320
Не могу разобраться с условием. LINQ

Не могу разобраться с условием. LINQ

Нужно найти все значение c, если значение value равно 5

298
Движение платформы вместе с персонажем

Движение платформы вместе с персонажем

Пытаюсь делать через setparent

460