是否可以在异步方法中 return 指向 IAsyncEnumerable 的指针?

Is it possible to return a pointer to an IAsyncEnumerable in an async method?

我有一个处理数据的异步方法reader,它带有传递给它的委托函数。委托的目的是从 reader 构造域对象并将其返回给调用者。我想要一个构造委托和 reader 的中间方法,并且 return 从被调用的方法生成 IAsyncEnumerable。我能够做到这一点的唯一方法是实际使用 IAsyncEnumerable 并从中间方法中产生这些结果。尝试仅 return 直接导致编译器错误,指出我必须使用 yield return 或 yield break.

delegate T ProcessFunc<T>(MySqlDataReader reader);

async IAsyncEnumerable<T> ProcessReader<T>(MySqlDataReader reader, ProcessFunc<T> transformFunc)
{
    while (await reader.ReadAsync() != false)
    {
        yield return transformFunc(reader);
    }

    await reader.DisposeAsync();
}

public async IAsyncEnumerable<DataObject> GetDataObjectsAsync()
{
    ProcessFunc<DataObject> processFunc = (reader) =>
    {
        var id = reader.GetGuid( "id" );

        return new DataObject(id);
    };

    var reader = await GetDataObjectsReaderAsync(); //Constructs appropriate sqlcommand and returns a mysqldatareader

    //only way i can get this to function
    //would like to just be able to write: return ProcessReader(reader, processFunc)
    //so as not to chain another enumerable
    await foreach (var obj in ProcessReader( reader, processFunc ))
        yield return obj; 
}

在这种情况下,您可以将 ProcessReader 更改为接受 Task<MySqlDataReader> 而不是 MySqlDataReader,这样您就可以使 GetDataObjectsAsync 同步:

async IAsyncEnumerable<T> ProcessReader<T>(Task<MySqlDataReader> readerTask, ProcessFunc<T> transformFunc)
{
    var reader = await readerTask;
    while (await reader.ReadAsync() != false)
    {
        yield return transformFunc(reader);
    }

    await reader.DisposeAsync();
}

public IAsyncEnumerable<DataObject> GetDataObjects()
{
    ProcessFunc<DataObject> processFunc = (reader) =>
    {
        var id = reader.GetGuid( "id" );

        return new DataObject(id);
    };

    return ProcessReader(GetDataObjectsReaderAsync(), processFunc)
}

或者将您的 GetDataObjectsAsync 方法更改为 return Task<IAsyncEnumerable<DataObject>>:

public async Task<IAsyncEnumerable<DataObject>> GetDataObjectsAsync()
{
    ProcessFunc<DataObject> processFunc = (reader) =>
    {
        var id = reader.GetGuid( "id" );

        return new DataObject(id);
    };

    var reader = await GetDataObjectsReaderAsync(); //Constructs appropriate sqlcommand and returns a mysqldatareader

    return ProcessReader(reader, processFunc); 
}