Qu’est-ce que Func, comment et quand est-il utilisé

Qu’est-ce que Func et à quoi sert-il?

Func est un type de délégué prédéfini pour une méthode qui renvoie une valeur de type T

En d’autres termes, vous pouvez utiliser ce type pour référencer une méthode qui renvoie une valeur de T Par exemple

 public static ssortingng GetMessage() { return "Hello world"; } 

peut être référencé comme ça

 Func f = GetMessage; 

Pensez-y comme un espace réservé. Cela peut être très utile lorsque vous avez du code qui suit un certain modèle, mais ne doit pas être lié à une fonctionnalité particulière.

Par exemple, considérez la méthode d’extension Enumerable.Select .

  • Le modèle est le suivant: pour chaque élément d’une séquence, sélectionnez une valeur dans cet élément (par exemple, une propriété) et créez une nouvelle séquence constituée de ces valeurs.
  • L’ espace réservé est: une fonction de sélecteur qui obtient réellement les valeurs pour la séquence décrite ci-dessus.

Cette méthode prend un Func au lieu de toute fonction concrète. Cela lui permet d’être utilisé dans n’importe quel contexte où le modèle ci-dessus s’applique.

Par exemple, disons que j’ai une List et que je veux juste le nom de chaque personne dans la liste. Je peux le faire:

 var names = people.Select(p => p.Name); 

Ou dire que je veux l’ âge de chaque personne:

 var ages = people.Select(p => p.Age); 

Tout de suite, vous pouvez voir comment j’ai pu exploiter le même code représentant un motif (avec Select ) avec deux fonctions différentes ( p => p.Name et p => p.Age ).

L’alternative serait d’écrire une version différente de Select chaque fois que vous vouliez numériser une séquence pour un type de valeur différent. Donc, pour obtenir le même effet que ci-dessus, il me faudrait:

 // Presumably, the code inside these two methods would look almost identical; // the only difference would be the part that actually selects a value // based on a Person. var names = GetPersonNames(people); var ages = GetPersonAges(people); 

Avec un délégué agissant comme espace réservé, je me libère de devoir écrire le même schéma encore et encore dans des cas comme celui-ci.

Func représente une fonction qui prend les arguments (T1, T2, …, Tn) et renvoie Tr.

Par exemple, si vous avez une fonction:

 double sqr(double x) { return x * x; } 

Vous pourriez le sauvegarder en tant que variable de fonction:

 Func f1 = sqr; Func f2 = x => x * x; 

Et puis utilisez exactement comme vous utiliseriez sqr:

 f1(2); Console.WriteLine(f2(f1(4))); 

etc.

Rappelez-vous cependant que c’est un délégué, pour plus d’informations, consultez la documentation.

Func et les autres delegates Func génériques prédéfinis ( Func , Func et autres) sont des delegates génériques qui renvoient le type du dernier paramètre générique.

Si vous avez une fonction qui doit renvoyer différents types, selon les parameters, vous pouvez utiliser un délégué Func , en spécifiant le type de retour.

C’est juste un délégué générique prédéfini. En l’utilisant, vous n’avez pas besoin de déclarer chaque délégué. Il y a un autre délégué prédéfini, Action , qui est le même mais renvoie un vide.

Je trouve Func très utile lorsque je crée un composant à personnaliser “à la volée”.

Prenez cet exemple très simple: un PrintListToConsole .

Un object très simple qui imprime cette liste d’objects sur la console. Vous voulez laisser le développeur qui l’utilise personnaliser la sortie.

Par exemple, vous voulez le laisser définir un type particulier de format numérique, etc.

Sans func

Tout d’abord, vous devez créer une interface pour une classe qui prend l’entrée et génère la chaîne à imprimer sur la console.

 interface PrintListConsoleRender { Ssortingng Render(T input); } 

Ensuite, vous devez créer la classe PrintListToConsole qui prend l’interface créée précédemment et l’utilise sur chaque élément de la liste.

 class PrintListToConsole { private PrintListConsoleRender _renderer; public void SetRenderer(PrintListConsoleRender r) { // this is the point where I can personalize the render mechanism _renderer = r; } public void PrintToConsole(List list) { foreach (var item in list) { Console.Write(_renderer.Render(item)); } } } 

Le développeur qui doit utiliser votre composant doit:

  1. implémenter l’interface

  2. passer la vraie classe à la PrintListToConsole

     class MyRenderer : PrintListConsoleRender { public Ssortingng Render(int input) { return "Number: " + input; } } class Program { static void Main(ssortingng[] args) { var list = new List { 1, 2, 3 }; var printer = new PrintListToConsole(); printer.SetRenderer(new MyRenderer()); printer.PrintToConsole(list); ssortingng result = Console.ReadLine(); } } 

Utiliser Func c’est beaucoup plus simple

A l’intérieur du composant, vous définissez un paramètre de type Func qui représente une interface d’une fonction qui prend un paramètre d’entrée de type T et retourne une chaîne (la sortie pour la console)

 class PrintListToConsole { private Func _renderFunc; public void SetRenderFunc(Func r) { // this is the point where I can set the render mechanism _renderFunc = r; } public void Print(List list) { foreach (var item in list) { Console.Write(_renderFunc(item)); } } } 

Lorsque le développeur utilise votre composant, il transmet simplement au composant l’implémentation du type Func , c’est-à-dire une fonction qui crée la sortie pour la console.

 class Program { static void Main(ssortingng[] args) { var list = new Array[1, 2, 3]; var printer = new PrintListToConsole(); printer.SetRenderFunc((o) => "Number:" + o); printer.Print(); ssortingng result = Console.ReadLine(); } } 

Func vous permet de définir une interface de méthode générique à la volée. Vous définissez le type de l’entrée et le type de sortie. Simple et concis