奇数返回语法语句
我知道这可能听起来很奇怪,但我不知道如何在互联网上search这个语法,也不知道究竟是什么意思。
所以我看了一些更多的LINQ代码,然后我注意到了这个方法
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,它支持本地function….
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(); }
诀窍是,_()在使用之后被声明,这非常好。
实用的地方function
上面的例子只是一个演示如何使用内联方法,但是如果你打算只调用一次方法,那么很可能是没用的。
但是在上面的例子中,如Phoshi和Luaan的评论所提到的那样 ,使用本地function是有优势的。 因为带有yield return的函数不会被执行,除非有人迭代它,在这种情况下,将执行局部函数外部的方法,并且即使没有人重复该值也将执行参数validation。
我们多次在方法中重复了代码,让我们看这个例子。
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... }
考虑更简单的例子
void Main() { Console.WriteLine(Foo()); // Prints 5 } public static int Foo() { return _(); // declare the body of _() int _() { return 5; } }
_()
是在包含return语句的方法中声明的本地函数。