我最近一直在玩IAsyncEnumerables,有一件事我不明白它是如何在幕后工作的.

请考虑以下代码段:

private async Task Test()
{
    var t = new List<int>();

    await foreach (var number in Numbers().Take(5).ConfigureAwait(false))
    {
        t.Add(number);
    }
}

int[] myIntArray = new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

private async IAsyncEnumerable<int> Numbers()
{
    foreach (var element in myIntArray)
    {
        yield return element;
    }
}

所以让我烦恼的是,IAsyncEnumerable方法如何知道如何只执行5次,或者换句话说,它如何翻译.Take(5)方法,使其在执行时可以考虑传递的数字?

推荐答案

IAsyncEnumerable<T>是一个简单的接口,只有一个定义的方法--返回IAsyncEnumerator<T>,这并不是很复杂--它有MoveNextAsync个方法(将枚举器异步推进到集合的下一个元素)和Current个属性(在枚举器的当前位置获取集合中的元素),这类似于"普通"IEnumerable<T>.简而言之,所有LINQ方法都将使用这两种方法(如果我们不考虑某些特殊情况下的一些优化).

没有框架提供的用于异步枚举AFAIK的LINQ.如果您使用的是reactive extensions中的System.Linq.Async中的一个,那么它的实现基本上与"普通"Take相同,后者将源可枚举类包装到具有重载的MoveNext(source code)的特殊"分区"类中.在异步可枚举项的情况下,它是AsyncEnumerablePartition(source code),其在具体化时基本上将调用await MoveNextAsync(...),直到达到所请求的限制(即传递给Take),然后将停止执行.简化版本可能如下所示:

public static class Exts
{
    public static async IAsyncEnumerable<int> Take(this IAsyncEnumerable<int> source, int n)
    {
        var enumerator = source.GetAsyncEnumerator();
        while (n > 0)
        {
            if (await enumerator.MoveNextAsync())
            {
                yield return enumerator.Current;
                n--;
            }
            else
            {
                yield break;
            }
        }
    }
}

请注意,实际行为将取决于异步可枚举数本身,例如,如果它成批加载数据,则它将需要首先加载整个批.

Csharp相关问答推荐

利用.NET 8中的AddStandardResilienceDeliveries和AddStandardHedgingDeliveries实现Resiliency

错误NU 1301:无法加载源的服务索引

在依赖性注入和继承之间进行 Select

向类注入一个工厂来创建一些资源是一个好的实践吗?

编写DataAnnotations自定义验证器的多种方法

安装附加的. exe与Visual Studio

Razor视图Razor页面指向同一端点时的优先级

如何在C#中实现非抛出`MinBy`?

使用ExtractIconEx(或其他方式)提取最大的可用图标

带有可选参数的模拟方法返回意外的不同值,具体取决于可选的默认值

C#自定义验证属性未触发IsValid方法

发布.NET 8 Blazor WebAssembly独立应用程序以进行静态站点部署

类/值和日期的泛型方法

从GRPC连接创建ZipArchive

如何从原始图像到新创建的图像获得相同的特定 colored颜色 ,并且具有相同的 colored颜色 量和相同的宽度和高度?

在C#/ASP.NET Core 7中,什么可能导致POST请求作为GET请求发送

使用C#12中的主构造函数进行空判断

将列表转换为带有逗号分隔字符串形式的值的字典

无法使用直接URL通过PictureBox.ImageLocation加载图像

如何根据分割文本的块数来计算文本的大小?