cs_mathmax
Messages postés403Date d'inscriptionvendredi 28 octobre 2005StatutMembreDernière intervention31 août 2008
-
11 juin 2006 à 02:18
cs_tartour
Messages postés4Date d'inscriptionjeudi 8 décembre 2005StatutMembreDernière intervention 8 septembre 2009
-
25 août 2008 à 08:11
Bonjour,
Je me demandais quel est l'intéret de passer par un délégué quand on veut faire un événement. Pourquoi ne pas tous simplement appeler directement la methode à chaque fois que l'on veux que l'événement se déclanche. Quelle est l'intéret d'appeler le délégué qui lui renverra vers la méthode ? J'ai lu les tutoriaux sur MSDN, mais je dois dire que le rôle des délégués me parait encore obscure...
cs_badrbadr
Messages postés475Date d'inscriptionjeudi 19 juin 2003StatutMembreDernière intervention 3 novembre 20081 11 juin 2006 à 06:35
Les délégués sert de base pour les événements (d'ailleurs, les événements ne sont là que pour faciliter l'usage des délélgués).
Les délégués sont des pointeurs de fonctions. Sans eux, il n'y aurait pas de moyens (ou presque pas de moyens) de s'abonner à des événements.
Finalement, les délégués permettent de faire des appels asynchromes. C'est à dire des appels qui ne bloquent pas le thread qui appelle la fonction.
Bref, je comprends que les exemples sur msdn te donne l'impression qu'ils sont inutiles. Mais ces exemples ont juste une valeur académique. Ils te montrent pas comment les utiliser dans une "vraie" application.
Lutinore
Messages postés3246Date d'inscriptionlundi 25 avril 2005StatutMembreDernière intervention27 octobre 201241 11 juin 2006 à 12:05
Salut..
Tou simplement parce que la méthode on ne la connait pas à l'avance.. on impose avec le delegué qu'elle doit respecter une certaine signature, la signature c'est les paramètres qu'elle attend et sa valeur de retour , par exemple pour un évènement elle doit prendre un objet une classe dérivée de EventArgs.
Comme le dit Badrbadr les évènement ne sont là que pour simplifier et unifier la programmation entre les languages .NET, pour du code "internal" tu peux très bien utiliser seulement les délégués.
cs_mathmax
Messages postés403Date d'inscriptionvendredi 28 octobre 2005StatutMembreDernière intervention31 août 2008 11 juin 2006 à 14:02
Je ne comprends pas trop pourquoi tu dis que la méthode on ne la connais pas à l'avance. J'ai fais un petit programme pour tenter de me familiariser avec les délégués et les événements :
namespace evenement
{
public delegate void IdChangedEventHandler(object sender, ChangeIdEventArgs e);
public class personne
{
public event IdChangedEventHandler WhenIdChanged;
private static long _nbPersonnes = 0;
private string _nom, _prenom;
public personne(string n, string p)
{
_nbPersonnes++;
this.prenom = p;
this.nom = n;
}
public static long nbPersonnes
{
get { return _nbPersonnes; }
}
public string prenom
{
get { return _prenom; }
set
{.
if (_prenom != null)
WhenIdChanged(this, new ChangeIdEventArgs(_prenom + " -> " + value));
_prenom = value;
}
}
public string nom
{
get { return _nom; }
set
{
if (_nom != null)
WhenIdChanged(this, new ChangeIdEventArgs(_nom + " -> " + value));
_nom = value;
}
}
}
public class EventListener
{
private personne Personn;
public EventListener(personne P)
{
Personn = P;
Personn.WhenIdChanged += new IdChangedEventHandler(IdChanged);
}
public void IdChanged(object sender, ChangeIdEventArgs e)
{
Console.WriteLine("changement d'identité : " + e.EventText);
}
}
public class ChangeIdEventArgs : EventArgs
{
private string myEventText = null;
public ChangeIdEventArgs(string theEventText)
{
myEventText = theEventText;
}
public string EventText
{
get { return this.myEventText; }
}
}
class Program
{
static void Main(string[] args)
{
personne aPerson = new personne("Jackson", "Michael");
EventListener listener = new EventListener(aPerson);
aPerson.nom = "Jordan";
}
}
}
Ici, je ne vois pas trop l'utilité d'utiliser un délégué. Pourquoi ne pas tous simplement appeler directement la méthode IdChanged lorqu'on redéfini la propriété nom ou prenom ? De plus on connais très bien cette méthode à l'avance, non ?
Celà dit, peut-être que mon exemple n'était pas bien choisi et que ici l'utilisation d'un délégué n'était pas justifiée...
Mathmax
cs_coq
Messages postés6350Date d'inscriptionsamedi 1 juin 2002StatutMembreDernière intervention 2 août 2014101 11 juin 2006 à 14:14
Salut,
Et si l'utilisateur de ta classe décide de changer
Personn.WhenIdChanged += new IdChangedEventHandler(IdChanged); par
Personn.WhenIdChanged += new IdChangedEventHandler(IdChangedBis); avec IdChangedBis en private (car normalement une méthode de ce genre l'est), comment fais tu ? :-)
/*
coq
MVP Visual C#
*/
Vous n’avez pas trouvé la réponse que vous recherchez ?
cs_badrbadr
Messages postés475Date d'inscriptionjeudi 19 juin 2003StatutMembreDernière intervention 3 novembre 20081 11 juin 2006 à 14:25
Voyons coq, c facile
Tout d'abord, tu développes ton propre hôte pour le CLR.
Ensuite, on load l'assembly dans l'appdomain de ton choix, tu t'assures de changer les private en public en hookant un truc dans le JIT. Faut pas oublier de diminuer la sécurité juste avant et le tour est joué
Bon, c'est tout de même plus facile que d'utiliser des délégués, non, t'es pas d'accord ????
Lutinore
Messages postés3246Date d'inscriptionlundi 25 avril 2005StatutMembreDernière intervention27 octobre 201241 11 juin 2006 à 14:29
Dans la propriété Nom et Prenom de la classe Personne essaye d'appeler la méthode IdChanged à la place d'utiliser un délégué.. tu vas voir que ça se complique.. et encore il n y a qu'une seule classe EventListener abonnée à l'évènement là.
Maintenant si tu compiles ta classe Personne dans une librarie toute seule.. Comment fais tu pour savoir d'avance la fonction qu'il faudra appeler lors de l'évènement dans un programme client qui ajoutera ta dll à son projet ??
cs_badrbadr
Messages postés475Date d'inscriptionjeudi 19 juin 2003StatutMembreDernière intervention 3 novembre 20081 11 juin 2006 à 14:50
Bon, à titre académique, je vais présenter une méthode qui permet à peu près de faire la même chose que les délégués mais avec beaucoup moins d’élégance.
Nous allons avoir une classe appelée Win32 et qui a comme rôle d’envoyer un message quand la souris bouge au-dessus d’un contrôle.
Pour se faire, définissions notre événement sous forme d’interface :
public
interface
IMouseMove
{
void OnMouseMove(int x, int y);
}
Ensuite, nos “contrôles” vont implémenter cette interface afin de pouvoir recevoir l’événement :
public
class
MyButton : IMouseMove
{
publicvoid OnMouseMove(int x, int y)
{
//faire qqch
}
}
public
class
MyPanel : IMouseMove
{
publicvoid OnMouseMove(int x, int y)
{
//faire qqch
}
}
Maintenant, il reste juste à créer notre classe qui va déclencher l’événement et qui permet aussi de s’inscrire (et se désinscrire de celui-ci) :
public
class
Win32
{
ArrayList clients = newArrayList();
publicvoid Subscribe(IMouseMove i)
{
clients.Add(i);
}
publicvoid UnSubscribe(IMouseMove i)
{
clients.Remove(i);
}
publicvoid FireMouseMoveEvent(int x, int y)
{
foreach (IMouseMove i in clients)
{
i.OnMouseMove(x, y);
}
}
}
Bon, maintenant, si vous vous retrouvé dans un monde sans délégués, vous savez comment réagir :D
cs_mathmax
Messages postés403Date d'inscriptionvendredi 28 octobre 2005StatutMembreDernière intervention31 août 2008 11 juin 2006 à 19:29
Merci pour toutes vos réponses.
Coq :
Je ne vois pas trop ce que tu veux dire. IdChangedBis est une méthode de EventListener ? Si oui, qu'est ce que ça change pour l'utilisateur de changer le nom de la méthode dans le délégué, plutôt que de renommer les 2 méthodes. C'est un peu plus court certe, mais est-ce là le seul avantage ?
Lutinore :
Dans la propriété Nom et Prenom de la classe Personne essaye d'appeler
la méthode IdChanged à la place d'utiliser un délégué.. tu vas voir que
ça se complique..
Oui ça se complique puisque ma méthode est dans la calsse EventListener et qu'elle n'est donc pas accessible. Mais si je la définie au même niveau que les classes, elle est accesible par ces dernières et ça ne pose pas de problème non ?
et encore il n y a qu'une seule classe EventListener abonnée à l'évènement là.
Pourquoi si il y en a plusieurs ça complique ?
Maintenant si tu compiles ta classe Personne dans une librarie toute
seule.. Comment fais tu pour savoir d'avance la fonction qu'il faudra
appeler lors de l'évènement dans un programme client qui ajoutera ta
dll à son projet ??
Il faudra de toute façon que je la compile avec la définition de IdChangedEventHandler, donc autant la compiler plutôt avec la méthode. Cependant il est vrai que je laisse comme ça à l'utilisateur de ma classe le choix de nommer et construire la méthode comme il le veux. Est-ce là l'avantage ?
Badrbadr :
Merci pour ton exemple. Crois-tu vraiement que ça va être plus court à écrire avec des délégués ? Ou qu'entends-tu par "propre" ?
Mathmax
cs_coq
Messages postés6350Date d'inscriptionsamedi 1 juin 2002StatutMembreDernière intervention 2 août 2014101 11 juin 2006 à 19:40
Ok, je crois que je n'ai pas réussi à faire passer le message que je voulais.
Appliquons maintenant l'exemple à quelquechose que tu ne peux pas recompiler : la BCL du Framework .Net.
Tu serais abligé d'utiliser le nom de méthode utilisé dans le Framework, comme tu ne peux pas le recompiler.
Disons que le clic sur un bouton lance l'appel d'une méthode "ButtonClick" sur "l'abonné".
Prenons donc un Form avec 2 boutons, tu ne veux logiquement pas faire la même action sur les 2 boutons, pourtant ils necessitent tous les 2 une méthode avec le même nom.
Donc tu ne peux mettre qu'un bouton par formulaire :-)
En plus de ça tu es obligé de passer par un mécanisme d'interface comme dans l'exemple de badrbadr, car le Framework ne connait pas à l'avance le type de ton formulaire, donc il ne pourrait faire l'appel de méthode.
Avec le mécanisme d'event/delegate, peu importe le nom que l'utilisateur donne à la méthode associée à l'event, c'est ce mécanisme qui fait la liaison entre le déclencheur de l'event et la méthode en elle même.
cs_mathmax
Messages postés403Date d'inscriptionvendredi 28 octobre 2005StatutMembreDernière intervention31 août 2008 11 juin 2006 à 21:30
Ok merci pour ces précisions coq, je crois que j'ai assez bien compris pourquoi on n'appelle pas directement la méthode. On veut que l'utilisateur de la classe puisse pouvoir créer, pour chaque instance d'objet, la méthode adéquate quand l'évenement se produit. En fait quand on construit la classe, on s'occupe seulement de quand l'évenement se produit et non pas de ce qui va être réalisé suite à cet évenement. Petite question seulement, qu'appelles-tu "l'abonné" ?
J'avoue en revanche ne pas avoir tout compris à l'histoire d'interface et de type de formulaire...
Mathmax
cs_coq
Messages postés6350Date d'inscriptionsamedi 1 juin 2002StatutMembreDernière intervention 2 août 2014101 11 juin 2006 à 21:53
Par "l'abonné" je désigne l'objet qui s'abonne à l'évènement (dans notre cas, le formulaire donc).
Un formulaire n'est rien d'autre qu'une classe nommée "FormPrincipal" (par exemple) héritant de la classe de base Form.
Il s'agit donc d'un type à part entière.
Hors la seule façon d'être sûr qu'un type possède une méthode définie, c'est :
- que son type de base définisse une méthode abstract qui sera dont l'implémentation sera fournie dans le type dérivé
- qu'il implémente une interface définissant la méthode en question
cs_mathmax
Messages postés403Date d'inscriptionvendredi 28 octobre 2005StatutMembreDernière intervention31 août 2008 11 juin 2006 à 23:46
Merci, mais je ne suis pas sûr d'avoir bien compris le rôle d'une méthode abstract. S'agit-il d'une méthode "vide" que l'on place dans la classe encêtre afin d'obliger toutes ses classes dérivés à posséder cette méthode ? Si c'est le cas, il faut alors modifier l'ancêtre de FormPrincipal pour lui rajouter cette classe abstract. Il faut donc rajouter cette méthode pour la classe Form. C'est possible ?
Pourquoi faut-il en plus créer une interface ? De plus l'interface sera forçément l'ancêtre de FormPrincipal donc Form ce qui n'est pas possible, non ?
En revanche, je ne vois pas trop ce que tu veux dire par "un type à part entière".