Instruction de syntaxe de retour impair

Je sais que cela peut paraître étrange, mais je ne sais même pas comment rechercher cette syntaxe sur Internet et je ne suis pas sûr de ce que cela signifie exactement.

J’ai donc surveillé du code MoreLINQ et j’ai remarqué cette méthode

public static IEnumerable DistinctBy(this IEnumerable source, Func keySelector, IEqualityComparer comparer) { if (source == null) throw new ArgumentNullException(nameof(source)); if (keySelector == null) throw new ArgumentNullException(nameof(keySelector)); return _(); IEnumerable _() { var knownKeys = new HashSet(comparer); foreach (var element in source) { if (knownKeys.Add(keySelector(element))) yield return element; } } } 

Quelle est cette déclaration de retour étrange? return _(); ?

C’est C # 7.0 qui supporte les fonctions locales ….

 public static IEnumerable DistinctBy( this IEnumerable source, Func keySelector, IEqualityComparer 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 _LocalFunction() { var knownKeys = new HashSet(comparer); foreach (var element in source) { if (knownKeys.Add(keySelector(element))) yield return element; } } } 

C # actuel avec Func

 public static IEnumerable DistinctBy( this IEnumerable source, Func keySelector, IEqualityComparer comparer) { if (source == null) throw new ArgumentNullException(nameof(source)); if (keySelector == null) throw new ArgumentNullException(nameof(keySelector)); Func> func = () => { var knownKeys = new HashSet(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 correct.

Utilisation pratique des fonctions locales

L’exemple ci-dessus est juste une démonstration de la façon dont la méthode inline peut être utilisée, mais très probablement si vous allez invoquer la méthode une seule fois, elle ne sera d’aucune utilité.

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 rendement de rendement 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 parameters sera effectuée même si personne n’itérera la valeur.

Nous avons répété plusieurs fois la méthode du code, regardons cet exemple.

  public void ValidateCustomer(Customer customer){ if( ssortingng.IsNullOrEmpty( customer.FirstName )){ ssortingng error = "Firstname cannot be empty"; customer.ValidationErrors.Add(error); ErrorLogger.Log(error); throw new ValidationError(error); } if( ssortingng.IsNullOrEmpty( customer.LastName )){ ssortingng 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(ssortingng value, ssortingng error){ if(!ssortingng.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... } 

Prenons l’exemple plus simple

 void Main() { Console.WriteLine(Foo()); // Prints 5 } public static int Foo() { return _(); // declare the body of _() int _() { return 5; } } 

_() est une fonction locale déclarée dans la méthode contenant l’instruction return.