Buat IAsyncEnumerable kosong

25

Saya memiliki antarmuka yang ditulis seperti ini:

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

Saya ingin menulis implementasi kosong yang tidak mengembalikan item, seperti:

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

Jika itu adalah IEnumerable biasa, saya akan melakukannya return Enumerable.Empty<string>();, tetapi saya tidak menemukannya AsyncEnumerable.Empty<string>().

Penanganan masalah

Saya menemukan ini yang berfungsi tetapi cukup aneh:

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

Ada ide?

kubus45
sumber

Jawaban:

28

Jika Anda menginstal System.Linq.Asyncpaket, Anda harus dapat menggunakannya AsyncEnumable.Empty<string>(). Ini contoh lengkapnya:

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
    }
}
Jon Skeet
sumber
Terima kasih atas balasan secepatnya dan sarannya. Saya berharap ada sesuatu dalam kerangka itu.
cube45
@ cube45: Saya biasanya menganggap System.Linq.Async"hampir bagian dari kerangka kerja". Ada sangat sedikit yang hanya di netstandard2.1 ketika datang ke IAsyncEnumerable<T>.
Jon Skeet
@ cube45 Saya akan berhati-hati tentang tidak menggunakan paket ada banyak quark dengan aliran async Anda akan menemukan ketika Anda mulai menggunakannya lebih banyak kecuali Anda benar-benar tahu apa yang Anda lakukan, saya akan benar-benar di nugget.
Filip Cordas
Terima kasih atas jawaban anda Saya tidak pernah menggunakan IAsyncEnumerable sebelumnya, dan saya hanya bereksperimen, tidak melakukan sesuatu yang "nyata". Anda mungkin benar, paket itu mungkin berguna.
cube45
Ada masalah jika sedang digunakan dengan efcore github.com/dotnet/efcore/issues/18124
Pavel Shastov
11

Jika karena alasan apa pun Anda tidak ingin menginstal paket yang disebutkan dalam jawaban Jon, Anda dapat membuat metode AsyncEnumerable.Empty<T>()seperti ini:

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);
    }
}

Catatan: Jawabannya tidak mengecilkan hati menggunakan System.Linq.Asyncpaket. Jawaban ini memberikan implementasi singkat AsyncEnumerable.Empty<T>()untuk kasus-kasus yang Anda butuhkan dan Anda tidak bisa / tidak ingin menggunakan paket. Anda dapat menemukan implementasi yang digunakan dalam paket di sini .

Reza Aghaei
sumber
Terima kasih atas jawaban anda. Memang, itu akan menjadi pilihan juga. Saya pikir saya lebih suka cara itu daripada menginstal paket lain. Saya akan menandai yang ini sebagai diterima. Nitpick: Anda mengatakan "metode ekstensi" sementara itu hanya metode statis di kelas statis.
cube45
1
@ cube45: Jadi, apakah Anda tidak berencana menggunakan fungsionalitas LINQ dengan urutan asinkron yang terlibat? Karena begitu Anda ingin melakukan apa pun yang biasanya Anda lakukan dengan LINQ sinkron, Anda akan memerlukan System.Linq.Async.
Jon Skeet