C'est juste un raccourci pour les délégués avec une signature spécifique. Pour bien comprendre les réponses ci-dessous, vous devrez comprendre les délégués ;-)
Theo Lenndorff
2
Dans la réponse de @Oded, il ditIf you have a function that needs to return different types, depending on the parameters, you can use a Func delegate, specifying the return type.
LCJ
Réponses:
76
Func<T>est un type de délégué prédéfini pour une méthode qui renvoie une valeur du 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
Mais cela peut aussi représenter une fonction statique à un argument =)
Ark-kun
2
@ Ark-kun non, ce n'est pas correct. La définition de Func<T>est delegate TResult Func<out TResult>(). Aucun argument. Func<T1, T2>serait une fonction qui prend un argument.
Brian Rasmussen
4
Non, j'ai raison. static int OneArgFunc(this string i) { return 42; }Func<int> f = "foo".OneArgFunc;. =)
Ark-kun
1
C'est une méthode d'extension qui est spéciale.
Brian Rasmussen
La seule particularité à ce sujet est l' Extensionattribut qui n'est lu que par les compilateurs C # / VB.Net, pas par CLR. Fondamentalement, les méthodes d'instance (contrairement aux fonctions statiques) ont un 0ème paramètre caché "this". Ainsi, la méthode d'instance à 1 argument est très similaire à la fonction statique à 2 arguments. Ensuite, nous avons des délégués qui stockent l' objet cible et le pointeur de fonction . Les délégués peuvent stocker le premier argument dans target ou ne pas le faire.
Ark-kun
87
Considérez-le comme un espace réservé. Cela peut être très utile lorsque vous avez du code qui suit un certain modèle mais qui n'a pas besoin d'être lié à une fonctionnalité particulière.
Par exemple, considérez la Enumerable.Selectméthode d'extension.
Le modèle est le suivant: pour chaque élément d'une séquence, sélectionnez une valeur de cet élément (par exemple, une propriété) et créez une nouvelle séquence composée de ces valeurs.
L' espace réservé est: une fonction de sélection qui obtient en fait les valeurs de la séquence décrite ci-dessus.
Cette méthode prend une Func<T, TResult>au lieu de n'importe quelle 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 un List<Person>et je veux juste le nom de chaque personne de la liste. Je peux le faire:
var names = people.Select(p => p.Name);
Ou dis 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.Nameet p => p.Age).
L'alternative serait d'écrire une version différente de Selectchaque fois que vous souhaitez analyser 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 modèle encore et encore dans des cas comme celui-ci.
Ensuite, vous devez créer la classe PrintListToConsole<T>qui prend l'interface précédemment créée et l'utilise sur chaque élément de la liste.
classPrintListToConsole<T>{privatePrintListConsoleRender<T> _renderer;publicvoidSetRenderer(PrintListConsoleRender<T> r){// this is the point where I can personalize the render mechanism
_renderer = r;}publicvoidPrintToConsole(List<T>list){foreach(var item inlist){Console.Write(_renderer.Render(item));}}}
Le développeur qui a besoin d'utiliser votre composant doit:
À l'intérieur du composant, vous définissez un paramètre de type Func<T,String>qui représente une interface d'une fonction qui prend un paramètre d'entrée de type T et renvoie une chaîne (la sortie pour la console)
classPrintListToConsole<T>{privateFunc<T,String> _renderFunc;publicvoidSetRenderFunc(Func<T,String> r){// this is the point where I can set the render mechanism
_renderFunc = r;}publicvoidPrint(List<T>list){foreach(var item inlist){Console.Write(_renderFunc(item));}}}
Lorsque le développeur utilise votre composant, il transmet simplement au composant l'implémentation du Func<T, String>type, c'est-à-dire une fonction qui crée la sortie pour la console.
classProgram{staticvoidMain(string[] args){varlist=newList<int>{1,2,3};// should be a list as the method signature expectsvar printer =newPrintListToConsole<int>();
printer.SetRenderFunc((o)=>"Number:"+ o);
printer.Print(list);string result =Console.ReadLine();}}
Func<T>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 la sortie. Simple et concis.
Merci d'avoir publié ce Marco. Cela m'a vraiment aidé. J'essaie de comprendre func depuis un moment et je l'utilise également activement dans ma programmation. Cet exemple effacera le chemin. J'ai dû ajouter la méthode StampaFunc car elle était omise dans le code d'origine, ce qui l'empêchait de s'afficher.
Siwoku Adeola
1
Je pense qu'il y a une ligne manquée dans l'exemple Func, où est l'appel pour la fonction d'impression ou StampaFunc?
Bashar Abu Shamaa
11
Func<T1,R>et les autres génériques prédéfinis Funcdélégués ( Func<T1,T2,R>, Func<T1,T2,T3,R>et d' autres) sont délégués 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, en fonction des paramètres, vous pouvez utiliser un Funcdélégué, en spécifiant le type de retour.
Il s'agit simplement d'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 existe un autre délégué prédéfini Action<T, T2...>, qui est le même mais renvoie void.
Il n'est peut-être pas trop tard pour ajouter des informations.
Somme:
Le Func est un délégué personnalisé défini dans l'espace de noms System qui vous permet de pointer vers une méthode avec la même signature (comme le font les délégués), en utilisant 0 à 16 paramètres d'entrée et qui doit renvoyer quelque chose.
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.
Réponses:
Func<T>
est un type de délégué prédéfini pour une méthode qui renvoie une valeur du typeT
.En d'autres termes, vous pouvez utiliser ce type pour référencer une méthode qui renvoie une valeur de
T
. Par exemplepeut être référencé comme ceci
la source
Func<T>
estdelegate TResult Func<out TResult>()
. Aucun argument.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 n'est lu que par les compilateurs C # / VB.Net, pas par CLR. Fondamentalement, les méthodes d'instance (contrairement aux fonctions statiques) ont un 0ème paramètre caché "this". Ainsi, la méthode d'instance à 1 argument est très similaire à la fonction statique à 2 arguments. Ensuite, nous avons des délégués qui stockent l' objet cible et le pointeur de fonction . Les délégués peuvent stocker le premier argument dans target ou ne pas le faire.Considérez-le comme un espace réservé. Cela peut être très utile lorsque vous avez du code qui suit un certain modèle mais qui n'a pas besoin d'être lié à une fonctionnalité particulière.
Par exemple, considérez la
Enumerable.Select
méthode d'extension.Cette méthode prend une
Func<T, TResult>
au lieu de n'importe quelle 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 un
List<Person>
et je veux juste le nom de chaque personne de la liste. Je peux le faire:Ou dis que je veux l' âge de chaque personne:
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
etp => p.Age
).L'alternative serait d'écrire une version différente de
Select
chaque fois que vous souhaitez analyser une séquence pour un type de valeur différent. Donc, pour obtenir le même effet que ci-dessus, il me faudrait:Avec un délégué agissant comme espace réservé, je me libère de devoir écrire le même modèle encore et encore dans des cas comme celui-ci.
la source
Func<T1, T2, ..., Tn, Tr>
représente une fonction, qui prend (T1, T2, ..., Tn) arguments et renvoie Tr.Par exemple, si vous avez une fonction:
Vous pouvez l'enregistrer comme une sorte de variable de fonction:
Et puis utilisez exactement comme vous utiliseriez sqr:
etc.
Rappelez-vous cependant que c'est un délégué, pour des informations plus avancées, reportez-vous à la documentation.
la source
Je trouve
Func<T>
très utile lorsque je crée un composant qui doit être personnalisé "à la volée".Prenons cet exemple très simple: un
PrintListToConsole<T>
composant.Un objet très simple qui imprime cette liste d'objets sur la console. Vous voulez laisser le développeur qui l'utilise personnaliser la sortie.
Par exemple, vous voulez lui laisser définir un type particulier de format de nombre et ainsi de suite.
Sans Func
Tout d'abord, vous devez créer une interface pour une classe qui prend l'entrée et produit la chaîne à imprimer sur la console.
Ensuite, vous devez créer la classe
PrintListToConsole<T>
qui prend l'interface précédemment créée et l'utilise sur chaque élément de la liste.Le développeur qui a besoin d'utiliser votre composant doit:
implémenter l'interface
passer la vraie classe au
PrintListToConsole
Utiliser Func c'est beaucoup plus simple
À l'intérieur du composant, vous définissez un paramètre de type
Func<T,String>
qui représente une interface d'une fonction qui prend un paramètre d'entrée de type T et renvoie une chaîne (la sortie pour la console)Lorsque le développeur utilise votre composant, il transmet simplement au composant l'implémentation du
Func<T, String>
type, c'est-à-dire une fonction qui crée la sortie pour la console.Func<T>
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 la sortie. Simple et concis.la source
Func<T1,R>
et les autres génériques prédéfinisFunc
délégués (Func<T1,T2,R>
,Func<T1,T2,T3,R>
et d' autres) sont délégués 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, en fonction des paramètres, vous pouvez utiliser un
Func
délégué, en spécifiant le type de retour.la source
Il s'agit simplement d'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 existe un autre délégué prédéfini
Action<T, T2...>
, qui est le même mais renvoie void.la source
Il n'est peut-être pas trop tard pour ajouter des informations.
Somme:
Le Func est un délégué personnalisé défini dans l'espace de noms System qui vous permet de pointer vers une méthode avec la même signature (comme le font les délégués), en utilisant 0 à 16 paramètres d'entrée et qui doit renvoyer quelque chose.
Nomenclature et mode d'emploi:
Définition:
Où il est utilisé:
Il est utilisé dans les expressions lambda et les méthodes anonymes.
la source