Sobes.tech
Назад к вопросам
Junior — Middle
60

Чем отличаются механизмы yield и async/await при работе с асинхронностью в программировании?

Ответ от нейросети

sobes.tech AI

Что хотят услышать интервьюеры:

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

Определение:

yield в C# применяется внутри итераторных методов и позволяет возвращать элементы по одному, сохраняя состояние между вызовами. Метод с yield не выполняется целиком сразу, а продолжает работу по мере обхода коллекции.

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

Пример использования:

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

async/await — когда нужно дождаться ответа от HTTP-запроса или чтения файла без блокировки потока.

using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;

class Demo
{
    public static IEnumerable<int> GetNumbers()
    {
        yield return 1;
        yield return 2;
        yield return 3;
    }

    public static async Task<string> DownloadTextAsync(string url)
    {
        using var client = new HttpClient();
        return await client.GetStringAsync(url);
    }
}

Пояснение кода:

В GetNumbers() оператор yield return возвращает по одному числу при каждом следующем запросе перечислителя. Метод запоминает, на каком месте остановился, и продолжает с этого места при следующем MoveNext().

В DownloadTextAsync() await приостанавливает метод, пока GetStringAsync не завершится. При этом поток не блокируется, а управление возвращается вызывающему коду, и метод продолжится после получения результата.

Ключевые моменты:

  • yield работает с IEnumerable / IEnumerator и предназначен для последовательностей, а не для асинхронных операций.
  • async/await работает с Task / Task<T> и нужен для асинхронного ожидания.
  • yield лениво производит значения, async/await — неблокирующе ожидает завершения операции.
  • Метод с yield не может использовать await без изменения семантики и возвращаемого типа.
  • async/await не делает код автоматически параллельным; он упрощает именно асинхронность.
  • Для интервью важно подчеркнуть: yield — про итерацию, async/await — про выполнение операций без блокировки потока.