Метод, не названный при использовании возврата урожая

Я испытываю немного затруднений из-за метода, в котором я использую yield return это не работает...

public IEnumerable<MyClass> SomeMethod(int aParam)
{
    foreach(DataRow row in GetClassesFromDB(aParam).Rows)
    {
        yield return new MyClass((int)row["Id"], (string)row["SomeString"]);
    }    
}

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

Однако, если я изменяюсь на...

public IEnumerable<MyClass> SomeMethod(int aParam)
{
    IList<MyClass> classes = new List<MyClass>();

    foreach(DataRow row in GetClassesFromDB(aParam).Rows)
    {
         classes.Add(new MyClass((int)rows["Id"], (string)row["SomeString"]);
    }

    return classes;
}

Это работает просто великолепно.

Я не понимаю, почему первый метод никогда не работает, Вы могли помочь мне в понимании, что происходит здесь?

8
задан 15 March 2017 в 08:25
поделиться

2 ответа

Версия «yield» запускается только тогда, когда вызывающий объект фактически начинает перечислять возвращенную коллекцию.

Если, например, вы получите только коллекцию:

var results = SomeObject.SomeMethod (5);

и ничего не сделаете с ней, SomeMethod не будет выполняться.

Только когда вы начнете перечислять коллекцию results , она попадет.

foreach (MyClass c in results)
{
    /* Now it strikes */
}
8
ответ дан 5 December 2019 в 17:35
поделиться

yield return методы фактически преобразуются в классы конечного автомата, которые лениво извлекают информацию - только когда вы ее действительно запрашиваете. Это означает, что для фактического извлечения данных вам необходимо перебрать результат вашего метода.

// Gives you an iterator object that hasn't done anything yet
IEnumerable<MyClass> list = SomeMethod(); 

// Enumerate over the object
foreach (var item in list ) {
  // Only here will the data be retrieved. 
  // The method will stop on yield return every time the foreach loops.
}

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

В этом конкретном случае маловероятно, что у вас будет какое-либо преимущество от использования блока итератора по сравнению с обычным, потому что ваш GetClassesFromDb () также не является одним из них. Это означает, что при первом запуске он будет извлекать все данные одновременно. Блоки итераторов лучше всего использовать, когда вы можете обращаться к элементам по одному, потому что таким образом вы можете остановиться, если они вам больше не нужны.

2
ответ дан 5 December 2019 в 17:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: