在Batch方法中使用Select(x => x)的目的是什么?
我正在查看Batch
方法的源代码,我已经看到了这个:
// Select is necessary so bucket contents are streamed too yield return resultSelector(bucket.Select(x => x));
有一条我不太明白的评论。 我已经测试了这种方法而没有使用Select
,它运行良好。 但似乎有一些我缺少的东西。我想不出任何必要的例子,那么在这里使用Select(x => x)
的实际目的是什么?
以下是完整的源代码供参考:
private static IEnumerable BatchImpl( this IEnumerable source, int size, Func<IEnumerable, TResult> resultSelector) { TSource[] bucket = null; var count = 0; foreach (var item in source) { if (bucket == null) bucket = new TSource[size]; bucket[count++] = item; // The bucket is fully buffered before it's yielded if (count != size) continue; // Select is necessary so bucket contents are streamed too yield return resultSelector(bucket.Select(x => x)); bucket = null; count = 0; } // Return the last bucket with all remaining elements if (bucket != null && count > 0) yield return resultSelector(bucket.Take(count)); }
总结评论中的内容,理论上这是多余的。 在这种情况下,延迟执行无关紧要。 在yield
已经完成执行 :已经计算了bucket
内容,没有什么可以推迟。
迭代器块行为也没有问题 – 每次我们回到这个实现时,都会重置并重新创建bucket = null
(在yield
之后, bucket = null
)。 即使有人将结果转换为数组类型并修改它,我们也不在乎。
这种方法的一个优点似乎只是优雅:在对resultSelector
所有调用之间存在类型一致性。 如果没有“冗余” Select
,实际类型大部分时间都是TSource[]
,而IEnumerable
用于没有填充整个bucket
的尾随元素。
但是,可以想象以下场景:
- 使用此function的人注意到实际类型是数组
- 由于需要提高性能,他们将收到的批处理转换为
TSource[]
(例如,他们现在可以更有效地跳过元素, 因为Skip
没有针对数组进行优化 ) - 他们使用该方法没有任何问题,因为它们的情况下会发生
Count() % size == 0
直到,之后,会发生一个额外的元素弹出,导致最后一个yield
被执行。 现在,对TSource[]
将会失败。
因此,根据元素的数量和size
,方法在结果类型方面的行为会不一致(传递给给定的回调)。 可以想象其他复杂的情况,这种不一致可能会导致麻烦,例如某些ORM,根据实际类型,将对象序列化到不同的表中。 在这种情况下,数据片段最终会出现在不同的表格中。
这些场景当然都是基于其他一些错误,并没有certificate没有Select
实现是错误的。 然而,从某种意义上说,它对Select
更加友好 ,它将这种不幸情景的数量减少到最少。
上述就是C#学习教程:在Batch方法中使用Select(x => x)的目的是什么?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/989821.html