Каковы реальные применения доходности?

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

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

19.08.2008 22:45:19
7 ОТВЕТОВ
РЕШЕНИЕ

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

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

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

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

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

Что касается:

Ideally some problem that cannot be solved some other way

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

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

Доходность ключевого слова добавлена?

Полезен ли урожай вне LINQ?

11
23.05.2017 12:01:25

на самом деле я использую его нетрадиционным способом на моем сайте 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 час.

5
19.08.2008 22:51:19

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

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

1
19.08.2008 23:10:16

Другое хорошее использование для 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
19.08.2008 23:29:01

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

2
19.08.2008 23:39:32

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

1
19.08.2008 23:41:43

Вы также можете использовать 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);
    }
}
0
3.12.2013 22:53:29