Каковы реальные применения доходности? - PullRequest
13 голосов
/ 20 августа 2008

Я знаю, что делает yield, и я видел несколько примеров, но я не могу вспомнить реальные приложения, вы использовали его для решения какой-то конкретной проблемы?

(в идеале какая-то проблема, которая не может быть решена другим способом)

Ответы [ 7 ]

11 голосов
/ 07 ноября 2009

Я понимаю, что это старый вопрос (предварительно Джон Скит?), Но я сам недавно обдумывал этот вопрос. К сожалению, в текущих ответах здесь (на мой взгляд) не упоминается самое очевидное преимущество оператора yield.

Самым большим преимуществом оператора yield является то, что он позволяет перебирать очень большие списки с гораздо более эффективным использованием памяти, чем при использовании, скажем, стандартного списка.

Например, допустим, у вас есть запрос к базе данных, который возвращает 1 миллион строк. Вы можете извлечь все строки, используя DataReader, и сохранить их в List, следовательно, требуя list_size * row_size байтов памяти.

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

Более того, в коде, который использует Iterator, вы используете простой цикл foreach и можете решить выйти из цикла по мере необходимости. Если вы делаете перерыв рано, вы не форсируете извлечение всего набора данных, когда вам нужны только первые 5 строк (например).

Относительно:

Ideally some problem that cannot be solved some other way

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

Вот несколько более свежих вопросов и ответов, которые предоставляют более подробную информацию:

Добавлена ​​ли ценность ключевого слова?

Полезен ли урожай за пределами LINQ?

5 голосов
/ 20 августа 2008

на самом деле я использую это на своем сайте нетрадиционным способом IdeaPipe

public override IEnumerator<T> GetEnumerator()
{
    // goes through the collection and only returns the ones that are visible for the current user
    // this is done at this level instead of the display level so that ideas do not bleed through
    // on services
    foreach (T idea in InternalCollection)
        if (idea.IsViewingAuthorized)
            yield return idea;
}

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

2 голосов
/ 20 августа 2008

Одно интересное использование - это механизм асинхронного программирования, особенно для задач, которые выполняются в несколько этапов и требуют одинакового набора данных на каждом этапе. Двумя примерами этого могут быть Джеффри Рихтерс AysncEnumerator Часть 1 и Часть 2 . Среда параллелизма и координации (CCR) также использует этот метод Итераторы CCR .

1 голос
/ 20 августа 2008

Использование урожайности может предотвратить понижение до конкретного типа. Это удобно для того, чтобы потребитель коллекции не манипулировал ею.

1 голос
/ 20 августа 2008

Еще одним хорошим использованием для yield является выполнение функции над элементами IEnumerable и возвращение результата другого типа, например:

public delegate T SomeDelegate(K obj);

public IEnumerable<T> DoActionOnList(IEnumerable<K> list, SomeDelegate action)
{
    foreach (var i in list)
        yield return action(i);
}
1 голос
/ 20 августа 2008

Операторы LINQ в классе Enumerable реализованы как итераторы, созданные с помощью оператора yield. Он позволяет вам связывать такие операции, как Select () и Where (), фактически ничего не перечисляя, пока вы фактически не используете перечислитель в цикле, обычно с помощью оператора foreach . Кроме того, поскольку при вызове IEnumerator.MoveNext () вычисляется только одно значение, если вы решите остановить сбор данных в середине, вы сохраните снижение производительности при вычислении всех результатов.

Итераторы также могут использоваться для реализации других видов отложенной оценки, когда выражения оцениваются только тогда, когда это необходимо. Вы также можете использовать yield для более модных вещей, таких как сопрограммы.

0 голосов
/ 04 декабря 2013

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

void Main()
{
    var StartDate = DateTime.Parse("01/01/2013");
    var EndDate = DateTime.Parse("06/30/2013");
    foreach (var d in GetPayrollDates(StartDate, EndDate)) {
        Console.WriteLine(d);
    }
}

// Calculate payroll dates in the given range.
// Assumes the first date given is a payroll date.
IEnumerable<DateTime> GetPayrollDates(DateTime startDate, DateTime endDate, int     daysInPeriod = 14) {
    var thisDate = startDate;
    while (thisDate < endDate) {
        yield return thisDate;
        thisDate = thisDate.AddDays(daysInPeriod);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...