IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Forms Discussion :

[C#]Complément d'infos sur évènements


Sujet :

Windows Forms

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    612
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2008
    Messages : 612
    Par défaut [C#]Complément d'infos sur évènements
    Bonjour,

    Jusqu'à présent, j'ai utilisé les événements sans rencontrer de problèmes particuliers.

    Par exemple, si dans une classe dérivant de "Control" j'ai besoin d'un nouvel événement, je déclare simplement l'événement et je crée une méthode d'appel (pour un EventHandler de base et un EventArgs classique, sinon évidemment je dérive EventArgs et je crée mon propre délégué) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
            public event EventHandler ValuePropChanged;
     
            protected virtual void OnValuePropChanged(EventArgs e)
            {
                if (ValuePropChanged != null)
                    ValuePropChanged(this, e);
            }
    Ca semble ne poser aucun problème, c'est comme ça que j'avais compris la chose dès le début.

    Or, voici qu'en cherchant autre chose, je tombe sur ceci dans un contrôle du framework, dérivé aussi de "Control" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public event EventHandler ValueChanged
    {
        add
        {
            base.Events.AddHandler(EVENT_VALUECHANGED, value);
        }
        remove
        {
            base.Events.RemoveHandler(EVENT_VALUECHANGED, value);
        }
    }
    Donc, ajout explicite des méthodes Add et Remove et appel de AddHandler et RemoveHandler de la classe de base.

    Du coup, j'ai l'impression d'avoir raté quelque chose.
    Quelle est la différence de fonctionnement entre ma méthode et la méthode "officielle", et surtout si ces appels sont nécessaires, pourquoi mon code fonctionne-t-il?

    J'ai désassemblé mon propre code pour voir si le compilateur n'avait pas ajouté du code implicite, mais non, rien du tout.

    Merci d'avance,

    Claude

  2. #2
    Membre Expert Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Par défaut
    Si je ne me trompe, c'est pour des raisons de perf.

    Comme t'as pu le voir, les contrôles winforms ont une tripotée d'événements, de l'ordre de plusieurs dizaines. Quand tu déclares un event simple, sans surcharger add et remove, il me semble que le compilo C# crée une variable membre, qui contiendra les références des méthodes abonnées. Donc, par défaut, on aurait autant de ces membres que l'on a d'event. Ce qui est du gâchis de mémoire, puisqu'il est rare que l'on s'abonne a plus de trois ou quatre événements.
    Donc là, visiblement, le code que tu as vu par réflexion met toutes les références à toutes les méthodes abonnées à tous les event dans une unique collection.

    C'est aussi pour ça, qu'en MFC/Win32, les composants d'UI ne sont pas étendus avec des méthodes virtuelles à surcharger, mais par l'ajout de méthodes à une Message Map.

    Donc : à moins que tu ne crées un composant avec des dizaines d'events auxquels tu ne t'abonnes pas, pas la peine de se prendre la tête à surcharger add et remove

  3. #3
    Membre très actif
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    612
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2008
    Messages : 612
    Par défaut
    Merci

    Donc, si je suis bien le raisonnement, lorsque j'écris ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]
    public event MouseEventHandler MouseClick
    sur une série d'événements pour cacher ceux qui ne m'intéressent pas, en fait je détruits cette optimisation puisque ça va recréer la variable d'instance. Je devrais alors écrire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]
    public event MouseEventHandler MouseClick
    {
        add
        {
            base.MouseClick += value;
        }
        remove
        {
            base.MouseClick -= value;
        }
    }
    voir ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]
    public event MouseEventHandler MouseClick
    {
        add
        {
             return;
        }
        remove
        {
             return;
        }
    }

    ce qui éviterait sa création?

    Par contre, quelque chose me chiffonne dans ce concept (je suis plus habitué des petits systèmes en très bas niveau) :

    La mémoire programme et la mémoire donnée sur un PC, c'est la même physiquement. Et donc, ça m'interpelle que pour tenter, pour un évènement donné, de gagner l'emplacement d'une seule variable en ajoutant une surcharge à add et Remove (donc du code, donc de la mémoire) produit au final un gain mémoire. Je n'ai rien trouvé de static dans ces procédures et donc on a le code pour chaque instance du contrôle créée, non?
    Quelque chose doit m'échapper, LOL.

    Claude

  4. #4
    Membre Expert Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Par défaut
    Ah oui, j'avais oublié que c'était toi qui voulais aussi modifier la façon dont les propriétés sont initialisées dans le Designer.cs Tu cherches à masquer des event dans le designer ?
    Un peu de google m'amène là : http://discuss.fogcreek.com/dotnetqu...ow&ixPost=1138
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    [Browsable(false),EditorBrowsable(EditorBrowsableState.Never)]
    public event EventHandler DoubleClick
    {
        add
        {
            base.DoubleClick+=value;
        }
        remove
        {
            base.DoubleClick-=value;
        }
    }
    La même solution que celle que tu suggères, donc.

    Pour ce qui est du gain mémoire : le code, il est qu'une seule fois en mémoire, contrairement aux membres, qui eux sont dans chaque instance. Ce qu'on a voulu minimiser, c'est la place occupée par chaque instance.

  5. #5
    Membre très actif
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    612
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2008
    Messages : 612
    Par défaut
    Ah oui, j'avais oublié que c'était toi qui voulais aussi modifier la façon dont les propriétés sont initialisées dans le Designer.cs
    Oui, et j'y suis arrivé, du moins en partie. J'arrive à imposer un constructeur bien particulier par exemple, ou à modifier les paramètres passés au constructeur par le designer J'ai aussi compris qu'en remontant la hiérarchie du TypeConverter on pouvait arriver jusqu'aux constructions élémentaires, mais je ne suis pas allé si loin, imposer un constructeur me suffisait déjà.

    La même solution que celle que tu suggères, donc.
    Ok, alors ça veut dire que j'ai correctement compris ce que tu m'expliques, et ça infirme par contre plein d'exemples trouvés sur le net, comme quoi il faut toujours se méfier.

    le code, il est qu'une seule fois en mémoire, contrairement aux membres, qui eux sont dans chaque instance. Ce qu'on a voulu minimiser, c'est la place occupée par chaque instance.
    C'est là où manifestement je me suis planté dans le raisonnement. Je croyais que le code d'une méthode statique n'était qu'une fois en mémoire même en l'absence d'instance, mais que le code d'une méthode instanciée s'y trouvait autant de fois que d'instances créées et non une seule fois.

    Si je prends ça en compte, alors (si j'ai bien compris) l'optimisation est surtout efficace non pas si on a un grand nombre d'événements inutilisés, mais surtout si on a un grand nombre d'instances du contrôle créées. Dans ce cas, même avec un seul événement le gain peut être significatif, non?

    Merci,
    Claude

  6. #6
    Membre Expert Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Par défaut
    Citation Envoyé par ClaudeBg Voir le message
    Si je prends ça en compte, alors (si j'ai bien compris) l'optimisation est surtout efficace non pas si on a un grand nombre d'événements inutilisés, mais surtout si on a un grand nombre d'instances du contrôle créées. Dans ce cas, même avec un seul événement le gain peut être significatif, non?
    Ben c'est le produit des deux, logiquement. Coût total = coût unitaire * quantité.

    Mais dans ton cas, qui est celui de tous ceux présents sur ce forum, comme nous ne sommes pas concepteurs de bibliothèques de contrôles généralistes (combo, textbox, ...), on peut oublier ce genre de souci et créer gaiement nos événements avec la syntaxe classique pour nos contrôles spécialisés. Même si c'est toujours rigolo de voir comment ça fonctionne

    Quant au coup ds méthodes d'instance : une méthode d'instance, en programmation objet, n'est jamais qu'une méthode classique avec un paramètre caché, nommé "this", vers le type de l'instance courante. Ce n'est que de la syntaxe.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 20
    Dernier message: 16/10/2009, 14h29
  2. Complément d'Infos sur les .ini
    Par Fred2209 dans le forum Visual C++
    Réponses: 4
    Dernier message: 27/12/2006, 09h59
  3. recherche complément d'info sur instanceof
    Par SpaceFrog dans le forum Général JavaScript
    Réponses: 16
    Dernier message: 23/11/2006, 09h55
  4. Complément d'info sur l'utilisation de settimeout
    Par WhyMee dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 18/08/2006, 13h08
  5. [CR] Infos sur l'utilisation de dll
    Par step dans le forum SAP Crystal Reports
    Réponses: 11
    Dernier message: 09/08/2002, 11h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo