Qu'est-ce que la touche Func, comment et quand est-il utilisé
Qu'est-ce que Func<>
et à quoi sert-il?
- C'est juste un raccourci pour les délégués avec une signature spécifique. Pour comprendre pleinement les réponses ci-dessous, vous aurez besoin de comprendre délégués 😉
- Dans la réponse de @Oded il dit
If you have a function that needs to return different types, depending on the parameters, you can use a Func delegate, specifying the return type.
Vous devez vous connecter pour publier un commentaire.
Func<T>
est prédéfini type de délégué pour une méthode qui retourne une valeur de typeT
.En d'autres termes, vous pouvez utiliser ce type de référence, une méthode qui retourne une valeur de
T
. E. g.peut être référencé comme ce
Func<T>
estdelegate TResult Func<out TResult>()
. Pas d'arguments.Func<T1, T2>
serait une fonction qui prend un argument.static int OneArgFunc(this string i) { return 42; }
Func<int> f = "foo".OneArgFunc;
. =)Extension
attribut qui est lu uniquement par le C#/VB.Net compilateurs, pas CLR. Fondamentalement, les méthodes d'instance (à la différence des fonctions statiques) ont une face cachée 0e "ce" paramètre. Donc, 1-argument de la méthode d'instance est très similaire à la 2-argument de la fonction statique. Ensuite, nous avons les délégués magasin cible de l'objet et de pointeur de fonction. Les délégués peuvent stocker le premier argument dans cible, ou de ne pas le faire.Func<int>
ne peut point àpublic static int F(int i) { return 0; }
qui est statique d'un argument de la fonction. Vous avez besoinFunc<int, int>
pour que.string
argument au lieu deint
.Func<int>
peut point depublic static int F(string s) { return 0; }
. Comme je l'ai dit, il n'y a rien de spécial au sujet des méthodes d'extension (au niveau IL). Le IL code qui crée unFunc<int>
instance de la fonction est valable indépendamment de la fonction d'attributs. (Mais je dois dire que je ne suis pas en croire mes yeux quand j'ai vu le compilateur de le faire.)Func<MyClass, string>
délégué forme d'une méthode d'instance commeclass MyClass { public string MyMethod() { return ""; } }
.public static int F(string s) { return 0; }
etFunc<int> f = F;
ne compilera pas.Extension
pour que cela fonctionne. Mais sur le IL niveau il n'y a pas de différence entre les méthodes d'extension et de méthodes statiques. Vous pouvez écrirepublic static int StaticF(string s) { return 1; }
public static int ExtensionF(this string s) { return 2; }
Func<int> f = "a".ExtensionF;
, le compiler, puis remplacezExtensionF
avecStaticF
dans le IL, et il fonctionne très bien.Func<int>
ouFunc<string, int>
selon la syntaxe utilisée ("exemple" la syntaxe d'appel ou "statiques" la syntaxe d'appel) (ce qui affecte le nombre de paramètres libres et les paramètres libres de la signature).Penser que c'est un espace réservé. Il peut être très utile lorsque vous disposez d'un code qui suit un certain motif, mais n'ont pas besoin d'être liée à aucune fonctionnalité particulière.
Par exemple, considérons le
Enumerable.Select
méthode d'extension.Cette méthode prend un
Func<T, TResult>
au lieu de tout béton de la fonction. Cela lui permet d'être utilisé dans tout contexte où le schéma ci-dessus s'applique.Ainsi, par exemple, dire que j'ai un
List<Person>
et je veux juste le nom de chaque personne dans la liste. Je peux le faire:Ou de dire que je veux le âge de chaque personne:
Immédiatement, vous pouvez voir comment j'ai été en mesure de tirer parti de la même code représentant un modèle (avec
Select
) avec deux différents fonctions (p => p.Name
etp => p.Age
).L'alternative serait d'écrire une version différente de
Select
chaque fois que vous avez voulu analyse d'une séquence pour un autre type de valeur. Donc, pour obtenir le même effet que ci-dessus, j'aurais besoin de:Avec un délégué agissant en tant que substituant, je me libérer de d'avoir à écrire le même motif dans de tels cas.
Func<T1, T2, ..., Tn, Tr>
représente une fonction, qui prend (T1, T2, ..., Tn) arguments et retourne Tr.Par exemple, si vous avez une fonction:
Vous pouvez enregistrer comme une sorte de fonction de la variable:
Et ensuite utiliser exactement comme vous le feriez utiliser sqr:
etc.
N'oubliez pas, cependant, que c'est un délégué, pour les plus avancés d'informations reportez-vous à la documentation.
Func<T1,R>
et les autres prédéfinis génériqueFunc
délégués (Func<T1,T2,R>
,Func<T1,T2,T3,R>
et autres) sont génériques délégués qui renvoient le type de la dernière paramètre générique.Si vous avez une fonction qui doit revenir de différents types, en fonction des paramètres, vous pouvez utiliser un
Func
délégué, en précisant le type de retour.Je trouve
Func<T>
très utile lorsque je créer un composant qui doit être personnalisés "à la volée".Prendre cet exemple très simple: un
PrintListToConsole<T>
composant.Un objet très simple qui permet d'imprimer cette liste d'objets à la console.
Vous voulez laisser le développeur qui l'utilise personnaliser la sortie.
Par exemple, vous voulez laisser à lui de définir un certain type de format de nombre et ainsi de suite.
Sans Func
Tout d'abord, vous devez créer une interface pour une classe qui prend en entrée et produit la chaîne d'imprimer à la console.
Ensuite, vous devez créer la classe
PrintListToConsole<T>
qui prend déjà créées interface et l'utilise sur chaque élément de la liste.Le développeur qui a besoin d'utiliser votre composant a:
implémenter l'interface
passer le cours réel de la
PrintListToConsole
À l'aide de la touche Func c'est beaucoup plus simple
À l'intérieur de la partie, vous définissez un paramètre de type
Func<T,String>
que représente une interface d'une fonction qui prend un paramètre d'entrée de type T et retourne une chaîne de caractères (la sortie de la console)Lorsque le développeur utilise votre composant, il passe simplement à la composante de la mise en œuvre de la
Func<T, String>
type, c'est une fonction qui crée la sortie de la console.Func<T>
vous permet de définir une méthode générique de l'interface à la volée.Vous définissez quel type de l'entrée est et ce type de la sortie est.
Simple et concis.
C'est juste un prédéfini délégué générique. En l'utilisant, vous n'avez pas besoin de déclarer chaque délégué. Il y a un autre prédéfinis délégué,
Action<T, T2...>
, qui est la même, mais renvoie void.Peut-être qu'il n'est pas trop tard pour ajouter quelques infos.
Somme:
La touche Func est un délégué personnalisé défini dans l'espace de noms System qui permet de pointer vers une méthode avec la même signature (en tant que délégués ne), à l'aide de 0 à 16 paramètres d'entrée, et qui doit retourner quelque chose.
Nomenclature & how2use:
Définition:
Où il est utilisé:
Il est utilisé dans les expressions lambda et les méthodes anonymes.