c# - 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;
}
解决方案
不,基本上。"B" 的唯一用途是TList
它本身实际上是一个struct
; 然后,IL 可以使用“约束调用”来调用原始值,GetEnumerator()
而无需任何部分将原始struct TList
值装箱。
但是:一旦你调用GetEnumerator()
了 ,你又回到了IEnumerator<T>
陆地,它不会使用自定义迭代器。
在这种情况下,所有这些都没有实际意义,因为迭代器块也相当“分配”。所以...如果TList
您担心避免装箱,那么您可能对分配很着迷:在这种情况下,您也不会以这种方式编写迭代器块。
推荐阅读
- docker-compose - Jenkins CI 与 docker-compose - 如何正确停止容器
- java - google Safebrowsing api v4 总是返回空响应
- python - Remove quotations that surrounds substring but keep standalone quotes
- reactjs - 反应按钮 onClick 正确绑定,但无法正常工作
- python - matplotlib图例标签下key?
- python - 将 grequest 与地址块一起使用或一次全部使用的区别?
- java - 如何设置每次出现通知时都会播放的自定义声音?
- javascript - Javascript 事件处理程序从头开始执行所有函数
- android - 如何在 FragmentA 中对 FragmentB 进行编程?
- python - 为什么我的 keras 代码没有显示准确度值?