语法含义:return _(); IEnumerable <TSource> _()

Anh*_*Lai 13 c# syntax

在下面的C#代码中,我发现了_()奇怪的用法.有谁能解释这意味着什么?

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Mic*_*Liu 18

通过在return语句后插入换行符可以更容易地理解代码:

return _();

IEnumerable<TSource> _()
{
    var knownKeys = new HashSet<TKey>(comparer);
    foreach (var element in source)
    {
        if (knownKeys.Add(keySelector(element)))
            yield return element;
    }
}
Run Code Online (Sandbox Code Playgroud)

在此上下文中,下划线只是本地函数的任意名称(这是C#7.0中引入的新功能).如果您愿意,可以使用更具描述性的名称替换下划线:

return DistinctByHelper();

IEnumerable<TSource> DistinctByHelper()
{
    var knownKeys = new HashSet<TKey>(comparer);
    foreach (var element in source)
    {
        if (knownKeys.Add(keySelector(element)))
            yield return element;
    }
}
Run Code Online (Sandbox Code Playgroud)

作为本地函数,_(或DistinctByHelper)方法可以访问该DistinctBy方法的所有变量.

顺便说一句,这里有两个方法的原因是,如果任何参数为null,ArgumentNullException将在DistinctBy调用时立即抛出,而不是在枚举结果时抛出(由于yield return语句的存在).

  • 我*真的希望这种模式不会流行起来.那只是丑陋的. (4认同)
  • [docs](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7#local-functions) 给出了两个示例,说明为什么可以使用这样的本地函数。主要是在创建时而不是在迭代/等待时抛出异常。 (2认同)
  • 同意。下划线名称+在同一行开始定义不太适合我。 (2认同)