Deep C# vol.3 – await using

はじめに

この記事はDeep C# vol.2 – record structに続く記事となります。
第3回 Deep C# は await using を分析します。
内容としては第1回の Deep C# vol.1 – await foreaachのさらなる内奥に入り込むものともなります。
この記事を通して、await using は await foreach に必須の部品であり、非同期プログラミングの正しい実装のために必要だったことを理解していただけたら幸いです。

await using で非同期化される範囲

await using のどの部分が非同期化対象となるのでしょうか。
まずは簡単なサンプルを見てみましょう。

一見するとawait using(/*この中身*/) が非同期化されるように感じますが、実はこの部分に非同期コードを入れることは昔から可能でした。
コンストラクターは await にすることができないので、上記コードnew () は同期的です。
インスタンスの生成を非同期化するためには、非同期のファクトリーメソッドを実装する必要があります。
その場合以下のようになります。

では await using はどこを非同期化するのでしょうか。
await using() {} この範囲を抜けるときに呼び出される DisposeAsync() の呼び出しが新たな非同期化対象となります。

await using を解体する

古いC#で記述すると、このような処理と等価です。

この処理を非常にすっきりと記述できるようになりました。
この仕掛けは await foreach においてすべての範囲を非同期化するために必要なものであることが分かります。
(詳しくは Deep C# vol.1 – await foreaach をご覧ください。)

まとめ

このこと1つを取っても、C#は言語仕様を更新する際に .NET 自体の使用を変更せずに interface の追加とコンパイラによる新たな解釈とコード展開で乗り切っているものが多いことが分かると思います。
実は async / awaitdelegateyield return なども同じような形で言語拡張を成し遂げています。
それらもこのDeep C#のシリーズでひも解く予定です。
次回の題材は、近年になってパターンマッチング機能が充実してきた switch式 です。
ご期待ください。

最近の記事

  • 関連記事
  • おすすめ記事
  • 特集記事

アーカイブ

カテゴリー

PAGE TOP