为什么使用局部函数比内联代码更好?

Why is better to use a local function instead of just inlining the code?

我在 here 中找到了这段代码:

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> _(),后来才知道是在同一行调用和声明的局部函数。已完成 here.

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

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

我想说现在的版本更冗长,缩进更多,那么有什么好处呢?只是品味问题?

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

“内联”版本使用迭代器块,因此 none 代码(包括验证)将一直执行,直到调用代码开始迭代返回的 IEnumerable<TSource>

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

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