web-dev-qa-db-ja.com

空のIAsyncEnumerableを作成する

私はこのように書かれたインターフェースを持っています:

_public interface IItemRetriever
{
    public IAsyncEnumerable<string> GetItemsAsync();
}
_

次のように、アイテムを返さない空の実装を記述したいと思います。

_public class EmptyItemRetriever : IItemRetriever
{
    public IAsyncEnumerable<string> GetItemsAsync()
    {
       // What do I put here if nothing is to be done?
    }
}
_

それが単純なIEnumerableである場合、return Enumerable.Empty<string>();を使用しますが、AsyncEnumerable.Empty<string>()は見つかりませんでした。

回避策

私はこれがうまくいくのを見つけましたが、かなり奇妙です:

_public async IAsyncEnumerable<string> GetItemsAsync()
{
    await Task.CompletedTask;
    yield break;
}
_

何か案が?

24
cube45

_System.Linq.Async_ パッケージをインストールすると、AsyncEnumable.Empty<string>()を使用できるようになります。以下は完全な例です。

_using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        IAsyncEnumerable<string> empty = AsyncEnumerable.Empty<string>();
        var count = await empty.CountAsync();
        Console.WriteLine(count); // Prints 0
    }
}
_
26
Jon Skeet

何らかの理由でJonの回答に記載されているパッケージをインストールしたくない場合は、次のようにメソッドAsyncEnumerable.Empty<T>()を作成できます。

_using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public static class AsyncEnumerable
{
    public static IAsyncEnumerator<T> Empty<T>() => EmptyAsyncEnumerator<T>.Instance;

    class EmptyAsyncEnumerator<T> : IAsyncEnumerator<T>
    {
        public static readonly EmptyAsyncEnumerator<T> Instance = 
            new EmptyAsyncEnumerator<T>();
        public T Current => default!;
        public ValueTask DisposeAsync() => default;
        public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(false);
    }
}
_

注:答えは、_System.Linq.Async_パッケージの使用を妨げるものではありません。この回答は、必要な場合やパッケージを使用したくない/したくない場合のために、AsyncEnumerable.Empty<T>()の簡単な実装を提供します。パッケージで使用されている実装 here を見つけることができます。

10
Reza Aghaei