Đây là C # 7.0 hỗ trợ các chức năng cục bộ ....
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 # hiện tại với 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();
}
Bí quyết là, _ () được khai báo sau khi nó được sử dụng, điều này hoàn toàn ổn.
Sử dụng thực tế các chức năng địa phương
Ví dụ trên chỉ là một minh chứng về cách có thể sử dụng phương thức nội tuyến, nhưng rất có thể nếu bạn định gọi phương thức chỉ một lần, thì nó không có ích gì.
Nhưng trong ví dụ trên, như đã đề cập trong các bình luận của Phoshi và Luaan , có một lợi thế là sử dụng hàm cục bộ. Vì hàm có trả về lợi nhuận sẽ không được thực thi trừ khi ai đó lặp lại nó, trong trường hợp này, phương thức bên ngoài hàm cục bộ sẽ được thực thi và việc xác thực tham số sẽ được thực hiện ngay cả khi không ai lặp lại giá trị.
Nhiều lần chúng tôi đã lặp lại mã trong phương thức, hãy xem ví dụ này ..
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...
}
Tôi có thể tối ưu hóa điều này với ...
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...
}
return _(); IEnumerable<TSource> _()
:?