我知道这听起来可能很奇怪,但我甚至不知道如何在互联网上搜索这种语法,而且我也不知道确切的意思.

所以我看了一些MoreLINQ代码,然后我注意到了这个方法

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 _();

推荐答案

这是支持本地功能的C#7.0....

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

        // This is basically executing _LocalFunction()
        return _LocalFunction(); 

        // This is a new inline method, 
        // return within this is only within scope of
        // this method
        IEnumerable<TSource> _LocalFunction()
        {
            var knownKeys = new HashSet<TKey>(comparer);
            foreach (var element in source)
            {
                if (knownKeys.Add(keySelector(element)))
                    yield return element;
            }
        }
    }

当前版本为Func<T>的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));

        Func<IEnumerable<TSource>> func = () => {
            var knownKeys = new HashSet<TKey>(comparer);
            foreach (var element in source)
            {
                if (knownKeys.Add(keySelector(element)))
                    yield return element;
            }
       };

        // This is basically executing func
        return func(); 

    }

诀窍是,()在使用后被声明,这是非常好的.

Pratical use of local functions

上面的示例只是演示如何使用内联方法,但如果只调用一次该方法,则很可能没有任何用处.

但在上面的例子中,正如PhoshiLuaan的 comments 中所提到的,使用局部函数有一个优点.由于除非有人对函数进行迭代,否则不会执行具有yield return的函数,因此在这种情况下,将执行本地函数之外的方法,并执行参数验证,即使没有人对该值进行迭代.

我们在方法中多次重复代码,让我们看一下这个示例.

  public void ValidateCustomer(Customer customer){

      if( string.IsNullOrEmpty( customer.FirstName )){
           string error = "Firstname cannot be empty";
           customer.ValidationErrors.Add(error);
           ErrorLogger.Log(error);
           throw new ValidationError(error);
      }

      if( string.IsNullOrEmpty( customer.LastName )){
           string error = "Lastname cannot be empty";
           customer.ValidationErrors.Add(error);
           ErrorLogger.Log(error);
           throw new ValidationError(error);
      }

      ... on  and on... 
  }

我可以用...

  public void ValidateCustomer(Customer customer){

      void _validate(string value, string error){
           if(!string.IsNullOrWhitespace(value)){

              // i can easily reference customer here
              customer.ValidationErrors.Add(error);

              ErrorLogger.Log(error);
              throw new ValidationError(error);                   
           }
      }

      _validate(customer.FirstName, "Firstname cannot be empty");
      _validate(customer.LastName, "Lastname cannot be empty");
      ... on  and on... 
  }

.net相关问答推荐

Long.MaxValue从Single到Long的转换导致溢出异常

找不到包Microsoft.VisualStudio.Azure.Containers.Tools.Targets

ECS服务无法从Cognito获取配置

仅使用 .NET GetBytes 方法转换有效字节而不创建问号

为什么具有可为空值的 struct 的 HashSet 非常慢?

每第 N 个字符/数字拆分一个字符串/数字?

什么决定了 Path.GetTempPath() 的返回值?

读取方法的属性值

ASP.NET Core 等效于 ASP.NET MVC 5 的 HttpException

C# 编译为 32/64 位,或任何 cpu?

所有数组在 C# 中都实现了哪些接口?

react 式扩展使用的好例子

用 double 替换 int 时的 Visual Studio 长编译

.NET 高级别的 .NET 4.0 和 .NET 4.5 的区别

读取 XML(从字符串)并获取一些字段 - 读取 XML 时出现问题

忽略 LINQ to XML 中的命名空间

如果锁定的对象内部发生异常,它会保持锁定状态吗?

obj 文件夹是为了什么而生成的?

如何判断uri字符串是否有效

LINQ 可以与 IEnumerable 一起使用吗?