Utilisation réelle des délégués C # [fermé]

16

Je pense que je comprends conceptuellement les délégués C #, cependant, j'ai du mal à trouver un exemple réel où ils seraient utiles. Pouvez-vous fournir des réponses détaillant comment les délégués C # ont été utilisés dans les applications réelles et quels problèmes ils vous ont permis de contourner.

AlexC
la source
2
Presque toutes les classes du framework .NET exposent un ensemble d'événements, alors voilà. C'est juste un moyen d'encapsuler une unité de travail. Par exemple, supposons que vous implémentiez une structure d'arbre binaire générique en C. Eh bien, la seule façon de classer votre arbre serait de prendre comme paramètre un pointeur de fonction qui savait faire le tri.
Ed

Réponses:

16

Le code GUI utilise des délégués pour gérer les événements, tels que les clics sur les boutons, les mouvements de fenêtre. L'utilisation du délégué vous permet d'avoir une fonction appelée chaque fois que l'événement se produit. Un exemple serait de lier une fonction qui enregistre des données à un bouton "Enregistrer" sur l'interface. Lorsque le bouton est cliqué, il est configuré pour exécuter la fonction qui enregistre les données. C'est utile dans la programmation GUI car tout votre programme peut attendre que l'utilisateur fasse quelque chose et vous n'avez aucun moyen de savoir ce qu'il fera en premier. L'utilisation de délégués permet à la fonctionnalité de votre programme d'être connectée à l'interface utilisateur de manière à ce que l'utilisateur puisse faire les choses comme il le souhaite.

FrustratedWithFormsDesigner
la source
2
++ Vous avez raison, mais je déteste toujours ça :-) alors il y a très longtemps, j'ai trouvé ça à la place .
Mike Dunlavey
12

Linq utilise les paramètres Func<T>et Action<T>délègue partout comme paramètres.

Ceux-ci vous permettent d'utiliser des expressions lambda comme paramètres et de définir l'action à entreprendre dans le cadre de la liste des paramètres.

Oded
la source
12

Pratiquement tout ce qui utilise le modèle d'observateur implémenterait probablement des délégués.

Lisez la description et vous imaginerez probablement certains scénarios dans lesquels vous les utiliseriez. La gestion des événements GUI est un exemple courant.

comment s'appelle-t-il
la source
+1, Le modèle de stratégie est vraiment là où les délégués brillent, c'est-à-dire que vous avez une classe où une méthode fait quelque chose, mais vous voulez que le quelque chose soit interchangeable et sans dépendance directe, les délégués ergo. Notez que les événements remplissent un peu le même besoin que les délégués, la différence est que vous utilisez des délégués lorsque vous devez réagir sur une valeur de retour, alors que vous déclenchez simplement des événements et tout ce qui sera.
Homde
9

Les délégués sont très utiles dans la programmation asynchrone.

Vous avez une classe qui fait des trucs de manière asynchrone et qui a un rappel. Vous pouvez avoir la méthode déléguée invoquée lors du rappel - et votre implémentation de classe fera la logique décrite dans votre méthode déléguée.

James Love
la source
9

Les délégués sont particulièrement utiles comme solution pour le trou dans le motif du milieu . Essentiellement, il existe de nombreux cas où vous souhaitez encapsuler un ensemble unique d'instructions à l'intérieur d'un groupe d'instructions commun. C'est particulièrement difficile si les instructions avant et après le bit unique doivent partager l'état. Avec les délégués, vous pouvez simplement passer un délégué dans une fonction. La fonction exécute le bit avant, exécute le délégué, puis exécute le bit après.

Scott Whitlock
la source
5

Dans le "vieux temps" des langages non-OOP comme Fortran et C, il était incroyablement utile de pouvoir recevoir un sous-programme un argument qui était un pointeur vers une fonction. Par exemple, leqsort fonction fonctionne avec une fonction de comparaison fournie par l'utilisateur. Il existe de nombreux sous-programmes pour résoudre des équations différentielles ordinaires ou pour optimiser des fonctions, et ils prennent tous des pointeurs de fonction comme arguments.

Dans les systèmes de fenêtrage, toutes sortes de rappels suivent le même schéma.

En Lisp, même au début, il y avait quelque chose appelé un "argument fonctionnel" ou FUNARG, qui n'était pas seulement une fonction, mais il contenait également un contexte de stockage où il pouvait se souvenir et interagir avec une partie du monde extérieur.

Ce même besoin existe dans les langages POO, sauf lorsque vous transmettez l'adresse d'une fonction, vous devez également transmettre l'adresse de l'objet dont la fonction est une méthode. C'est deux choses que vous devez passer. Donc, un délégué n'est que cela, et permet à ce bon vieux modèle d'être toujours utilisé.

Mike Dunlavey
la source
3

Voici un exemple simple qui montre à quel point les délégués peuvent être utiles pour créer du code simple qui suit le principe DRY. Il vous permet également de garder le code extrêmement près de l'endroit où il est nécessaire.

Action<Button, Action<Button>> prepareButton = 
    (btn, nxt) => { 
        btn.Height = 32;
        btn.Width= 64;
        nxt(btn);
    };

prepareButton(myBtn1, btn => btn.Text = "A");
prepareButton(myBtn2, btn => btn.Text = "B");
prepareButton(myBtn3, btn => btn.Text = "C");

Voici un exemple concret de l'avantage que les délégués offrent.

protected override void PageInitialize()
{
    const string selectCodeFormat = "javascript:selectCode('{0}', '{1}');";
    const string onClick = "return toggleElement(this);";

    Func<HtmlGenericControl> getElement = null;
    Action<HtmlGenericControl> setElement = null, addChild = null;
    HtmlGenericControl level1Element = null, level2Element = null, level3Element = null, level4Element = null;
    string className = null, code = null, description = null;           

    using (var records = Core.Database.ExecuteRecords("code.SocCodeTree"))
    {
        while (records.Read())
        {
            code = records.GetString("Code");
            description = records.GetString("Description"); 

            if (records.GetString("Level4") != "")
            {
                className = "Level4";
                setElement = e => level4Element = e;
                getElement = () => level4Element;
                addChild = e => level3Element.Controls.Add(e);
            }
            else if (records.GetString("Level3") != "")
            {
                className = "Level3";
                setElement = e => level3Element = e;
                getElement = () => level3Element;
                addChild = e => level2Element.Controls.Add(e);
            }
            else if (records.GetString("Level2") != "")
            {
                className = "Level2";
                setElement = e => level2Element = e;
                getElement = () => level2Element;
                addChild = e => level1Element.Controls.Add(e);
            }
            else
            {
                className = "Level1";
                setElement = e => level1Element = e;
                getElement = () => level1Element;
                addChild = e => Root.Controls.Add(e);
            }

            var child = new HtmlGenericControl("li");
            child.Attributes["class"] = className;
            var span = new HtmlGenericControl("span") { 
                InnerText = code + " - " + description + " - " 
            };
            span.Attributes["onclick"] = onClick;
            child.Controls.Add(span);
            var a = new HtmlAnchor() { 
                InnerText = "Select", 
                HRef = string.Format(selectCodeFormat, code, description) 
            };
            child.Controls.Add(a);
            setElement(new HtmlGenericControl("ul"));
            child.Controls.Add(getElement());
            addChild(child);    
        }
    }
}
ChaosPandion
la source
2

Ma première rencontre avec les délégués a été de rechercher une mise à jour du programme (formulaires Windows C # 3.5) en téléchargeant un fichier à partir de mon site Web, mais pour éviter que la vérification de la mise à jour ne bloque tout le programme, j'ai utilisé un délégué et un thread pour le faire de manière asynchrone.

Ken
la source
1

J'ai vu des implémentations intéressantes du modèle de stratégie qui utilise efficacement les délégués. (ie la stratégie est un délégué)

Celui que je regardais était pour le pathfinding où l'algorithme pour trouver le chemin était un délégué qui pouvait être (ré) assigné à l'exécution afin que différents algorithmes puissent être utilisés (BFS vs A * etc.)

Steven Evers
la source
1

De nombreux modèles GoF classiques peuvent être mis en œuvre avec des délégués: par exemple, le modèle de commande, le modèle de visiteur, le modèle de stratégie, le modèle d'usine et le modèle d'observateur peuvent souvent être mis en œuvre avec un simple délégué. Parfois, une classe est meilleure (par exemple lorsqu'une commande a besoin d'un nom ou qu'un objet de stratégie doit être sérialisé) mais dans la plupart des cas, utiliser Action<...>ou Func<...>est beaucoup plus élégant que de créer une interface dédiée à une méthode.

nikie
la source