为什么DefaultIfEmpty以这种方式实现?

时间:2016-05-09 14:24:34

标签: c# .net linq

追逐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;
}

3 个答案:

答案 0 :(得分:2)

DefaultIfEmpty需要采取以下措施:

  1. 如果源枚举没有条目,则需要充当具有单个值的枚举;默认值。

  2. 如果源枚举不为空,则需要充当源可枚举。因此,它需要产生所有值。

答案 1 :(得分:1)

因为当你开始枚举并且这个代码被用作另一个枚举级别时,你必须枚举整个事物。

如果你只是yield return第一个并停在那里,使用这个枚举器的代码会认为只有一个值。因此,您必须枚举所有内容并yield return转发。

你当然可以return enumerator这样做,但是在MoveNext()被调用之后不会这样,因为这会导致跳过第一个值。如果有另一种方法可以检查是否存在值,那么这就是实现它的方法。

答案 2 :(得分:1)

  

为什么在确定序列不为空后,代码必须遍历整个序列?

您可以在MSDN中阅读DefaultIfEmtpy返回值:

  

IEnumerable<T>对象,如果source为空,则包含TSource类型的默认值;否则,来源。

因此,如果枚举为空,则结果是包含默认值的可枚举,但如果枚举不为空,则返回相同的枚举(不仅是第一个元素)。

看起来这个方法似乎只是检查枚举是否包含元素,但事实并非如此。

  

为什么收益率最终会突破两次?

没有想法:)