うに.log

作業した内容のまとめとか読んだ本のまとめとか。間違っていることがあったらツッコミとかがもらえるといいなぁという願望のもと、とりあえずやったこと、調べたこと、理解していることしていないことをだらだら書いていく。勉強用のブログ。

C# 8 から導入された非同期ストリーム機能を使う

C# 8 以前では以下のような形で async/await を用いたコード上で yield return をすることはできなかった。

public async Task<IEnumerable<int>> GetHogesAsync()
{
    var items = await GetItemsAsync();
    foreach (var item in items)
    {
        yield return item + 10; // <- ここでコンパイルエラー
    }
}

これが、C# 8 で上記とは異なる形で、Task<IEnumerable<T>>の代わりに IAsyncEnumerable<T> を使うことで実現可能となった。

IAsyncEnumerable<T> は foreach を await することで非同期的に列挙することができる。

具体的には以下の構文となる。

await foreach (var item in items) {  }

現時点ではLINQ的な拡張が用意されていないため、もし LINQ のようなことがしたい場合は自前で用意する必要がある。*1

実際にはこんな感じなコードを書けばとりあえずLINQっぽく書くことができるようになる。

github.com

が、これだけだと例えば Task<IEnumerable<T>> な型だったり Task<T[]> な型だったりに対応できないので AsAsyncEnumerable<T> な拡張を用意してあげても良いかもしれない。
この場合、Task<IEnumerable<T>> だけだと C#型推論の関係上 Task<T[]> などを網羅できないので、個別に記述していく必要がある。

*1:NuGet が何かあるかもしれないけど未調査