追逐System.Linq.Enumerable.DefaultIfEmpty
的实施把我带到了这个方法。除了以下古怪的细节外,它看起来还不错:
// System.Linq.Enumerable
[IteratorStateMachine(typeof(Enumerable.<DefaultIfEmptyIterator>d__90<>))]
private static IEnumerable<TSource> DefaultIfEmptyIterator<TSource>(IEnumerable<TSource> source, TSource defaultValue)
{
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
if (enumerator.MoveNext())
{
do
{
yield return enumerator.Current;
}
while (enumerator.MoveNext());
}
else
{
yield return defaultValue;
}
}
IEnumerator<TSource> enumerator = null;
yield break;
yield break;
}
1)为什么一旦确定序列不为空,代码必须遍历整个序列?
2)为什么收益率最终会突破两次?
3)为什么在没有其他引用时,将enumerator
显式设置为null?
我会离开它:
// System.Linq.Enumerable
[IteratorStateMachine(typeof(Enumerable.<DefaultIfEmptyIterator>d__90<>))]
private static IEnumerable<TSource> DefaultIfEmptyIterator<TSource>(IEnumerable<TSource> source, TSource defaultValue)
{
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
if (enumerator.MoveNext())
{
do
{
yield return enumerator.Current;
}
// while (enumerator.MoveNext());
}
else
{
yield return defaultValue;
}
}
// IEnumerator<TSource> enumerator = null;
yield break;
// yield break;
}
答案 0 :(得分:2)
DefaultIfEmpty
需要采取以下措施:
如果源枚举没有条目,则需要充当具有单个值的枚举;默认值。
如果源枚举不为空,则需要充当源可枚举。因此,它需要产生所有值。
答案 1 :(得分:1)
因为当你开始枚举并且这个代码被用作另一个枚举级别时,你必须枚举整个事物。
如果你只是yield return
第一个并停在那里,使用这个枚举器的代码会认为只有一个值。因此,您必须枚举所有内容并yield return
转发。
你当然可以return enumerator
这样做,但是在MoveNext()
被调用之后不会这样,因为这会导致跳过第一个值。如果有另一种方法可以检查是否存在值,那么这就是实现它的方法。
答案 2 :(得分:1)
为什么在确定序列不为空后,代码必须遍历整个序列?
您可以在MSDN中阅读DefaultIfEmtpy
返回值:
IEnumerable<T>
对象,如果source为空,则包含TSource
类型的默认值;否则,来源。
因此,如果枚举为空,则结果是包含默认值的可枚举,但如果枚举不为空,则返回相同的枚举(不仅是第一个元素)。
看起来这个方法似乎只是检查枚举是否包含元素,但事实并非如此。
为什么收益率最终会突破两次?
没有想法:)