Ini adalah C # 7.0 yang mendukung fungsi lokal ....
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 # saat ini dengan 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();
}
Triknya adalah, _ () dideklarasikan setelah digunakan, yang tidak masalah.
Penggunaan praktis fungsi lokal
Contoh di atas hanyalah demonstrasi tentang bagaimana metode inline dapat digunakan, tetapi kemungkinan besar jika Anda akan memanggil metode hanya sekali, maka itu tidak ada gunanya.
Tetapi dalam contoh di atas, seperti yang disebutkan dalam komentar oleh Phoshi dan Luaan , ada keuntungan menggunakan fungsi lokal. Karena fungsi dengan hasil pengembalian tidak akan dijalankan kecuali seseorang mengulanginya, dalam kasus ini metode di luar fungsi lokal akan dijalankan dan validasi parameter akan dilakukan bahkan jika tidak ada yang akan mengulang nilainya.
Berkali-kali kita mengulangi kode dalam metode, mari kita lihat contoh ini ..
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...
}
Saya bisa mengoptimalkan ini dengan ...
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> _()
?