C'est C # 7.0 qui prend en charge les fonctions locales ...
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 # actuel avec 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();
}
L'astuce est que _ () est déclaré après son utilisation, ce qui est parfaitement bien.
Utilisation pratique des fonctions locales
L'exemple ci-dessus est juste une démonstration de la façon dont la méthode en ligne peut être utilisée, mais très probablement si vous allez invoquer la méthode une seule fois, alors cela ne sert à rien.
Mais dans l'exemple ci-dessus, comme mentionné dans les commentaires de Phoshi et Luaan , il y a un avantage à utiliser la fonction locale. Puisque la fonction avec yield return ne sera exécutée que si quelqu'un l'itère, dans ce cas, la méthode en dehors de la fonction locale sera exécutée et la validation des paramètres sera effectuée même si personne n'itérera la valeur.
Plusieurs fois, nous avons répété du code dans la méthode, regardons cet exemple.
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...
}
Je pourrais optimiser cela avec ...
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> _()
:?