この非常に単純な非同期メソッドについて考えてみましょう。
static async Task myMethodAsync()
{
await Task.Delay(500);
}
これをVS2013(Roslyn以前のコンパイラ)でコンパイルすると、生成されたステートマシンは構造体になります。
private struct <myMethodAsync>d__0 : IAsyncStateMachine
{
...
void IAsyncStateMachine.MoveNext()
{
...
}
}
VS2015(Roslyn)でコンパイルすると、生成されるコードは次のようになります。
private sealed class <myMethodAsync>d__1 : IAsyncStateMachine
{
...
void IAsyncStateMachine.MoveNext()
{
...
}
}
ご覧のとおり、Roslynはクラスを生成します(構造体ではありません)。古いコンパイラ(CTP2012だと思います)でのasync / awaitサポートの最初の実装もクラスを生成し、パフォーマンス上の理由から構造体に変更されたことを正しく覚えていれば。(場合によっては、ボクシングとヒープの割り当てを完全に回避できます…)(これを参照)
Roslynでこれが再び変更された理由を誰かが知っていますか?(これに関しては問題ありません。この変更は透過的であり、コードの動作を変更しないことを知っています。興味があります)
編集:
@Damien_The_Unbeliever(およびソースコード:))imhoからの回答がすべてを説明しています。説明されているRoslynの動作は、デバッグビルドにのみ適用されます(コメントに記載されているCLRの制限のために必要です)。リリースでは、構造体も生成します(そのすべての利点があります)。したがって、これは編集と続行の両方をサポートし、本番環境でのパフォーマンスを向上させるための非常に賢いソリューションのようです。興味深いもの、参加してくれたすべての人に感謝します!
async
ほとんどの場合、メソッドには真の非同期ポイントawait
があります。これは制御を生成するため、とにかく構造体をボックス化する必要があります。構造体は、たまたま同期して実行されたメソッドのメモリプレッシャーを軽減するだけだと思いますasync
。