8

我在这里找到了这段代码:

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector, IEqualityComparer<TKey>? comparer)
{
    if (source == null) throw new ArgumentNullException(nameof(source));
    if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));
    return _(); IEnumerable<TSource> _()
    {
        var knownKeys = new HashSet<TKey>(comparer);
        foreach (var element in source)
        {
            if (knownKeys.Add(keySelector(element)))
                yield return element;
        }
    }
}

起初我不明白这部分return _(); IEnumerable<TSource> _(),但我意识到它是在同一行中调用和声明的本地函数。它是在这里完成的。

我的问题是:与简单地内联该代码相比有什么优势吗?

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector, IEqualityComparer<TKey>? comparer)
{
    if (source == null) throw new ArgumentNullException(nameof(source));
    if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));
    var knownKeys = new HashSet<TKey>(comparer);
    foreach (var element in source)
    {
        if (knownKeys.Add(keySelector(element)))
            yield return element;
    }
}

我会说当前版本更冗长并且缩进更多,那么优势是什么?只是口味问题?

4

1 回答 1

13

如果或为 null,则具有本地方法的版本将立即抛出,因为它不是用迭代器块实现的。sourcekeySelector

“内联”版本使用迭代器块,因此在调用代码开始迭代返回的IEnumerable<TSource>.

一般来说,急切验证可以更容易地发现和理解错误:堆栈跟踪更清晰,并且在“发出中断的调用”和“看到失败”之间没有延迟。

同样的方法也可用于编写急切失败的任务返回方法:编写一个“常规”任务返回方法,该方法在执行验证后调用异步本地方法。

于 2021-06-25T13:36:19.267 回答