c# - 奇数返回语法语句

标签 c# .net c#-7.0

我知道这听起来很奇怪,但我什至不知道如何在互联网上搜索这个语法,而且我也不确定它的确切含义。

所以我看了一些 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;
            }
        }
    }

当前 C# 为 Func<T>

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

    }

诀窍是,_() 在使用后声明,这非常好。

局部函数的实际使用

上面的例子只是一个如何使用内联方法的演示,但是如果你打算只调用一次方法,那很可能是没有用的。

但在上面的例子中,正如 PhoshiLuaan 的评论中提到的,使用局部函数有一个优势。由于具有 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... 
  }

关于c# - 奇数返回语法语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45323628/

相关文章:

.net - ASP.NET/ADO.NET : Handling many database connections inside a . NET 对象?

c# - 在 WPF 中手动添加对 TextBox 的引用

c# - 开启类型变量

c# - Caliburn Micro 用户控制数据上下文

c# - 如何将此字符数组参数从 C 编码为 C# 中的字符串?

c# - 获取所有 Windows 8/10 toast 通知

c# - 禁用 TreeView 节点焦点提示

.net - 使用 LINQ to SQL 更新数据库?

debugging - 调试时如何删除异常 "Predefined type ' ValueTuple` 2' must be a struct"?

c# - Unsafe.As 从字节数组到 ulong 数组