実装するという選択肢もあります。いうメソッドが追加で定義されています。フローさせる必要がないのです。関連する歴史的なものです。機能を選択した場合にのみ現われます。フローしないメソッドには「Unsafe」というプレフィックスが付けられていました。[SecurityCritical]メソッドを呼び出すことができません。サポートする必要がある場合に備えて常に提供されています。フローするのは不要で重複した処理となります。フックするメソッドを公開しています。コンパイラはこのメソッドを直接使うことができますが、非常に重要な問題があります。するべきか、オブジェクトをどう関連付けるか、という問題です。そのステートマシンに対するメソッド呼び出しであることを思い出してください。サスペンド時にはこのステートマシンをヒープ上のどこかにコピーする必要があります。スタックはこのスレッド上で実行される、現在のフローとは全く無関係な後続の作業に使用されることになるからです。メソッドを呼び出す必要があります。取り込む必要があります。指すデリゲートを作るだけでは不十分なのです。発生します(デリゲートのこのオブジェクト参照は、新たにボックス化した構造体のコピーとなる)。これらは望ましくないオーバーヘッドです。ターゲットとして使用し、その過程で正しいコンテキストをキャプチャし、再開時にそのキャプチャしたコンテキストを使用して処理を実行するという、複雑な挙動をする必要があります。これは、コンパイラが出力するよりも多くのロジックを必要とします。いくつかの理由から、これらは代わりのヘルパーにカプセル化したいと考えています。第一に、各ユーザーのアセンブリに複雑なコードをたくさん含ませることになってしまうから。第二に、ビルダーパターンの実装の一環として、そのロジックをカスタマイズできるようにしたいから(後でプーリングについて話すときに、その理由の例を見ることになります)。第三に、このロジックを進化させ、改善することで、以前にコンパイルされたバイナリがより良く実行されるようにしたいからです。これは仮説ではありません。ときよりもはるかに効率的な実行ができるようになりました。Coreでどうなっているかを見ていきます。コンパイラが生成したコードをみると、サスペンドが必要な時に以下が起こる事が分かります。return;}ステートフィールド(<>1__state)には、メソッドの再開時にジャンプすべき場所を示すステートIDを格納しています。自体をフィールドに永続化しています。フックするようビルダーに要求します。実装しているからです。それを求める必要はありません。上で何をしているのかを以下に要約します。ExecutionContext.Capture()を使って、現在のコンテキストを取得。デリゲートを作成します。呼び出すデリゲートを取得することができるのです。このメソッドが初めてサスペンドする場合、まだボックス化されたステートマシンを持っていないので、この時点でボックス化します。して型付けされたローカル変数にオブジェクトを格納することによってヒープ上にもっていきます。ここからが難しいステップです。いうビルダーのフィールドが含まれています。いうフィールドが存在します。ビルダーはボックス化されたステートマシンを参照する必要があります。これにより、その後のサスペンド時に、すでにステートマシンをボックス化したことがわかり、再度ボックス化する必要がありません。変更し、適切なステートマシンを指すようにする必要があります。https://gist.github.com/nenoNaninu/41f8fa066dfd7dd7ef5377e2a2816747)。メソッドを呼び出し、そのボックスをフィールドに格納します。メソッドを呼び出し、ステートマシンをサスペンドしたところから実行します。上で起こることで、プロファイラでその結果を見る事ができます。されているかを見ることができます。以下の無為なプログラムを見てみましょう。強調するためだけに書いたものです。発生しているのでしょう?原因は幾つかあります。ExecutionContext。ミュータブルなデータ構造だからです。毎回コピーする必要があります。オブジェクトになります。