Почему "флаг" bool генерируется для конечного автомата async/wait?

Если вы скомпилируете следующий код:

private async Task<int> M()
{
    return await Task.FromResult(0);
}

И затем декомпилируйте его (я использовал dotPeek) и рассмотрю все важные методы MoveNext, вы увидите переменную bool, объявленную в начале; dotPeek выбрал для меня "флаг".

bool flag = true;

В этом случае вы увидите одного последующего пользователя этой переменной в заявлении case по умолчанию после запуска первого асинхронного вызова:

if (!awaiter.IsCompleted)
{
    this.\u003C\u003E1__state = 0;
    this.\u003C\u003Eu__\u0024awaiter11 = awaiter;
    this.\u003C\u003Et__builder.AwaitUnsafeOnCompleted<TaskAwaiter<int>, Program.\u003CP\u003Ed__10>(ref awaiter, ref this);
    flag = false;
    return;
}

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

В качестве фона я получаю удовольствие от процесса реализации async/await в Javascript через кросс-компилятор С# → JS. Я пытаюсь понять, в какой ситуации мне нужно учитывать полезность этого флага. На лице это кажется ложным, и поэтому я должен его игнорировать. Однако я хотел бы понять, почему компилятор С# представляет эту переменную - я подозреваю, что существуют более сложные выражения, которые используют эту переменную полезным способом.

Короче говоря: почему компилятор С# генерирует эту переменную flag?

Ответ 1

Следующий комментарий, опубликованный под вопросом, описывает его использование:

Оберните свой запрос ожидания в блок try-finally и установите некоторую переменную внутри блока finally. Я не совсем понимаю, что делает логика ИЛ, но я просто сделал быстрый взгляд, и похоже, что он использует эту переменную флага, чтобы проверить, когда выполнять код внутри блока finally.

-Ilian Pinzon

Также Стивен Клири добавляет полезную информацию для заинтересованного читателя. Он рекомендует эту серию блога и, в частности, этот пост в блоге.

@IlianPinzon имеет правильный ответ. Это объясняется более подробно на одном из сообщений Jon Skeet eduasync. Поскольку вы пишете кросс-компилятор, я настоятельно рекомендую прочитать эту целую серию.

-Stephen Cleary