Crea IAsyncEnumerable vuoto


25

Ho un'interfaccia che è scritta in questo modo:

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

Voglio scrivere un'implementazione vuota che non restituisce alcun elemento, in questo modo:

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

Se fosse un semplice IEnumerable, lo farei return Enumerable.Empty<string>();, ma non ne ho trovato AsyncEnumerable.Empty<string>().

soluzioni alternative

Ho trovato questo che funziona ma è abbastanza strano:

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

Qualche idea?

Risposte:


28

Se installi il System.Linq.Asyncpacchetto, dovresti essere in grado di usarlo AsyncEnumable.Empty<string>(). Ecco un esempio completo:

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

Grazie per la pronta risposta e il suggerimento. Speravo che qualcosa esistesse nel quadro.
cubo45,

@ cube45: generalmente considererei System.Linq.Async"praticamente parte del framework". C'è molto poco che è proprio in netstandard2.1 quando si tratta di IAsyncEnumerable<T>.
Jon Skeet,

@ cube45 Starei attento a non usare il pacchetto, ci sono molti quark con flussi asincroni che scoprirai quando inizi a usarlo di più a meno che tu non sappia davvero cosa stai facendo, lo farei davvero sulla pepita.
Filip Cordas,

Grazie per le tue risposte Non avevo mai usato IAsyncEnumerable prima e stavo solo sperimentando, non facendo qualcosa "per davvero". Probabilmente hai ragione, il pacchetto potrebbe essere utile.
cubo45,

C'è un problema se viene utilizzato con efcore github.com/dotnet/efcore/issues/18124
Pavel Shastov

11

Se per qualsiasi motivo non desideri installare il pacchetto menzionato nella risposta di Jon, puoi creare il metodo in AsyncEnumerable.Empty<T>()questo modo:

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

Nota: la risposta non scoraggia l'utilizzo del System.Linq.Asyncpacchetto. Questa risposta fornisce una breve implementazione dei AsyncEnumerable.Empty<T>()casi di cui hai bisogno e non puoi / non vuoi usare il pacchetto. Puoi trovare l'implementazione utilizzata nel pacchetto qui .


Grazie per la tua risposta. Anzi, anche questa sarebbe un'opzione. Penso che preferirei così piuttosto che installare un altro pacchetto. Segnerò questo come accettato. Nitpick: dici "metodo di estensione" mentre è solo un metodo statico in una classe statica.
cubo45,

1
@ cube45: Quindi non hai intenzione di utilizzare alcuna funzionalità LINQ con le sequenze asincrone coinvolte? Perché non appena vuoi fare qualsiasi cosa tu faccia normalmente con LINQ sincrono, avrai bisogno di System.Linq.Async.
Jon Skeet,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.