Правильное использование «доходности» - PullRequest
842 голосов
/ 04 января 2009

Ключевое слово yield является одним из тех ключевых слов в C #, которое продолжает меня мистифицировать, и я никогда не был уверен, что использую его правильно.

Из следующих двух частей кода, который является предпочтительным и почему?

Версия 1: Использование доходности

public static IEnumerable<Product> GetAllProducts()
{
    using (AdventureWorksEntities db = new AdventureWorksEntities())
    {
        var products = from product in db.Product
                       select product;

        foreach (Product product in products)
        {
            yield return product;
        }
    }
}

Версия 2: Возврат списка

public static IEnumerable<Product> GetAllProducts()
{
    using (AdventureWorksEntities db = new AdventureWorksEntities())
    {
        var products = from product in db.Product
                       select product;

        return products.ToList<Product>();
    }
}

Ответы [ 16 ]

8 голосов
/ 04 января 2009

Предполагая, что ваши продукты LINQ класс использует аналогичный выход для перечисления / итерации, первая версия более эффективна, потому что она дает только одно значение каждый раз, когда повторяется.

Второй пример - преобразование перечислителя / итератора в список с помощью метода ToList (). Это означает, что он вручную перебирает все элементы в перечислителе, а затем возвращает плоский список.

7 голосов
/ 04 января 2009

А что по этому поводу?

public static IEnumerable<Product> GetAllProducts()
{
    using (AdventureWorksEntities db = new AdventureWorksEntities())
    {
        var products = from product in db.Product
                       select product;

        return products.ToList();
    }
}

Я думаю, это намного чище. У меня нет VS2008 под рукой, чтобы проверить, хотя. В любом случае, если Products реализует IEnumerable (как кажется - он используется в операторе foreach), я бы вернул его напрямую.

5 голосов
/ 10 марта 2012

Я бы использовал версию 2 кода в этом случае. Поскольку у вас есть полный список доступных продуктов, и это то, что ожидает «потребитель» этого вызова метода, потребуется отправить полную информацию обратно вызывающей стороне.

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

Некоторые примеры, где можно использовать возвращение доходности:

  1. Сложный пошаговый расчет, при котором вызывающая сторона ожидает данные шага за раз
  2. Пейджинг в графическом интерфейсе - когда пользователь может никогда не дойти до последней страницы, и на текущей странице необходимо раскрыть только часть информации

Чтобы ответить на ваши вопросы, я бы использовал версию 2.

3 голосов
/ 04 января 2009

Вернуть список напрямую. Преимущества:

  • Это более понятно
  • Список можно использовать повторно. (итератор не) на самом деле не правда, спасибо, Джон

Вам следует использовать итератор (yield), когда вы думаете, что вам, вероятно, не придется выполнять итерацию до конца списка или когда у него нет конца. Например, клиентский вызов будет искать первый продукт, который удовлетворяет некоторому предикату, вы можете подумать об использовании итератора, хотя это надуманный пример, и, возможно, есть более эффективные способы его выполнения. В принципе, если вы заранее знаете, что весь список нужно будет рассчитать, просто сделайте это заранее. Если вы считаете, что это не так, рассмотрите возможность использования версии итератора.

1 голос
/ 04 августа 2015

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

Предположим, что разработчик фильтрует некоторую коллекцию, повторяет ее, а затем извлекает эти объекты в какую-то новую коллекцию. Этот вид сантехники довольно однообразный.

Подробнее о ключевом слове в этой статье .

0 голосов
/ 04 апреля 2017

Использование yield аналогично ключевому слову return , за исключением того, что оно возвращает генератор . И генератор объект будет проходить только один раз .

доходность имеет два преимущества:

  1. Вам не нужно читать эти значения дважды;
  2. Вы можете получить много дочерних узлов, но не обязательно помещать их все в память.

Есть еще одно ясное объяснение может быть, вам поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...