首页 > 解决方案 > C# 编译器可以在泛型类型上使用带有 foreach 的鸭子类型吗?

问题描述

已经确定编译器可以在迭代 List 或 Array 时执行鸭子类型以消除一些开销(请参阅C# 编译器中的鸭子类型),因为这些类型将其 IEnumerator 实现为堆栈分配的结构。

即使类型是通用的,但被限制为实现 IEnumerable,情况是否如此?

为了更具体,选项 B 的运行开销是否比 A 少?

A:

public static IEnumerable<T> Flatten<T>(this IEnumerable<IEnumerable<T>> collection)
{
    foreach (var subCollection in collection)
        foreach (var element in subCollection)
            yield return element;
}

乙:

public static IEnumerable<T> Flatten<TList, T>(this TList collection)
    where TList : IEnumerable<IEnumerable<T>>
{
    foreach (var subCollection in collection)
        foreach (var element in subCollection)
            yield return element;
}

标签: c#genericsduck-typing

解决方案


不,基本上。"B" 的唯一用途是TList 它本身实际上是一个struct; 然后,IL 可以使用“约束调用”来调用原始值,GetEnumerator() 而无需任何部分将原始struct TList值装箱。

但是:一旦你调用GetEnumerator()了 ,你又回到了IEnumerator<T>陆地,它不会使用自定义迭代器。

在这种情况下,所有这些都没有实际意义,因为迭代器块相当“分配”。所以...如果TList您担心避免装箱,那么您可能对分配很着迷:在这种情况下,您也不会以这种方式编写迭代器块。


推荐阅读