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

C# Discussion :

event abstract génère une erreur de compilation


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Mars 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 13
    Par défaut event abstract génère une erreur de compilation
    Bonjour

    Le code suivant génére une erreur de compilation.
    Quelqu'un peut-il m'expliquer pourquoi cette limitation ?
    Sachant que :
    - si on transforme l'event d'abstract en virtual, cela compile
    - si on déplace la méthode OnMyAction dans la class B cela compile aussi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
      public abstract class A
        {
            public abstract event Action MyAction;
            protected void OnMyAction()
            {
                MyAction(); // This line of code generate this error : The event 'MyAction' can only appear on the left hand side of += or -=	
            }
        }
     
        public class B : A
        {
            public override event Action MyAction;
        }
    Merci d'avance.

    Nara20

  2. #2
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    269
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 269
    Par défaut
    Bonjour,

    Penses à la nature d'un event. Il s'agit d'encapsuler la gestion d'un delegate, tout en concervant les possibilité d'usage du delegate. Ca sert juste à appeler des méthodes de façons découplés.
    Ca n'a pas de sens de vouloir rendre virtual ou abstract un événement.
    Ce qui a du sens, c'est de déclarer une méthode virtual ou abstract, et d'initier l'event avec cette méthode.

  3. #3
    Membre actif
    Homme Profil pro
    Architecte C#
    Inscrit en
    Février 2003
    Messages
    78
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte C#

    Informations forums :
    Inscription : Février 2003
    Messages : 78
    Par défaut
    Bonjour,

    Entièrement d'accord avec Antoine !

    la majorité des classes du framework.net utilisent les events de la facon suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    public class MyClass
    {
        public event Action MyAction;
     
        protected virtual void OnMyAction()
        {
            var handler = MyAction;
            if(handler != null)
            {
                handler();
            }
        }
    }
    cela te permet d'avoir ton évènement déclaré dans la classe mère tout en te permettant de le lancer dans les classes filles.

    une grosse partie (si ce n'est l'ensemble) des winfoms fonctionne comme ca.

    En espérant avoir apporté de l'eau a ton moulin, bonne après midi

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Ce qui ne marche pas n'est pas le fait de rendre l'évènement abstrait, mais le fait de l'utiliser comme tu le fais dans OnMyAction alors qu'il est abstrait.

    En fait, il y a une petite subtilité avec les évènements en C#... Un évènement est en réalité une paire d'accesseurs add/remove (un peu comme les accesseurs get/set pour une propriété). Ces accesseurs gèrent l'ajout et la suppression des handlers de l'évènement (généralement stockés dans un champ delegate du type correspondant, mais pas forcément).
    En pratique, l'implémentation sera quasiment toujours la même, donc C# nous facilite la vie en implémentant automatiquement les évènements si on ne fournit pas d'implémentation explicite. Quand tu écris ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public event EventHandler MyEvent;
    Le compilateur génère en fait quelque chose comme ça (un peu simplifié) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    // Champ delegate où sont stockés les handlers
    private EventHandler _myEvent;
     
    public event EventHandler MyEvent
    {
        add { _myEvent += value; }
        remove { _myEvent -= value; }
    }
    Dans ton code, le champ _myEvent n'est pas accessible directement; tu y accèdes via le nom de l'évènement MyEvent, et selon le contexte, le compilateur sait si tu fais référence au champ ou à l'évènement. Par exemple, si tu fais ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MyEvent(this, EventArgs.Empty);
    Le compilateur sait que tu fais en fait référence au champ _myEvent pour l'invoquer (car ça n'aurait pas de sens d'utiliser l'évènement lui-même dans ce contexte)

    Maintenant, si tu déclares l'évènement comme abstrait, le compilateur ne génère pas d'implémentation (puisque par définition un membre abstrait n'a pas d'implémentation). Il n'y a donc pas de champ correspondant à l'évènement qui stocke la liste des handlers... donc écrire MyAction() n'a pas de sens, puisque MyAction, dans ce contexte, fait référence à un évènement (utilisable seulement avec += et -=) et non à un champ de type delegate.

    Je t'invite à lire cet article pour mieux comprendre les subtilités des délégués et évènements

    Citation Envoyé par antoine.debyser Voir le message
    Ca n'a pas de sens de vouloir rendre virtual ou abstract un événement.
    En pratique ça ne se fait pas beaucoup, mais de là à dire que ça n'a pas de sens... ça veut juste dire que tu veux exposer un évènement mais que c'est les classes dérivées qui doivent l'implémenter. Ce n'est pas plus absurde qu'une méthode ou une propriété abstraite.
    Cela dit, dans le cas présent ça ne semble effectivement pas très utile...

  5. #5
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    269
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 269
    Par défaut
    Citation Envoyé par tomlev Voir le message
    En pratique ça ne se fait pas beaucoup, mais de là à dire que ça n'a pas de sens... ça veut juste dire que tu veux exposer un évènement mais que c'est les classes dérivées qui doivent l'implémenter. Ce n'est pas plus absurde qu'une méthode ou une propriété abstraite.
    Cela dit, dans le cas présent ça ne semble effectivement pas très utile...
    J'avais effectivement zapper le coté "propriété" de l'event.
    Mais honnêtement, si c'est pour laisser aux classes filles la gestion du delegate, autant juste exposer le delegate (en protected bien sur).

  6. #6
    Membre actif
    Homme Profil pro
    Architecte C#
    Inscrit en
    Février 2003
    Messages
    78
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte C#

    Informations forums :
    Inscription : Février 2003
    Messages : 78
    Par défaut
    Ca dépends comment tu veux l'utiliser, personnellement, je me force à penser :
    "Un évènement notifie qu'il s'est passé quelque chose, il ne démarre pas d'action"

    Du coup, c'est bien à la classe qui l'implémente de le lancer.

    Prenons l'exemple d'une classe qui traite les fichiers des dossiers:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    public interface IFileProcessor
    {
        void ProcessFiles();
    }
     
    public abstract class FileProcessorBase()
    {
        public event Action<string> FileHandled;
     
        protected virtual void OnFileHandled(string fileName)
        {
            var handler = FileHandled;
            if(handler != null)
            {
               handler(fileName);
            }
        }
     
        public void Process()
        {
            foreach(var file in GetConcernedFiles())
            {
                var content = GetFileContent();
                HandleFile(file, content);
                OnFileHandled(file);
                RemoveFileProcessed();
            }
        }
     
        public abstract void HandleFile(string filename, byte[] filecontent);
        public abstract IEnumerable<string> GetConcernedFiles();
        public abstract byte[] GetFileContent(string filename);
        public void RemoveFileProcessed(string filename);
    }
    Tout le traitement "fonctionnel" est présent dedans, et elle prévient meme quand un fichier est traité en lancant un évènement.

    elle appelle bien des méthodes abstraites, à chacune de tes surcharges d'implémenter "comment récupérer et traiter le fichier" et notifie les autres classes l'utilisant quand un fichier est traité.
    (Idéalement, avec un pattern stratégie histoire de ne pas mélanger les aspects techniques et fonctionnels, mais pour l'exemple, ca suffira )

    On peut très bien imaginer qu'un service lance le traitement mais qu'un autre s'abonne aux notifications de ta classe.

    En espérant avoir pu t'aider

  7. #7
    Membre averti
    Inscrit en
    Mars 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 13
    Par défaut
    Bonjour,

    Merci pour vos réponses.
    Effectivement, je ne vois pas (ou peu) l'interet de mettre l'événement en abstract.
    Dans mon cas, je pense qu'il s'agit d'une erreur de conception. Et vos réponses m'ont permit de me poser la bonne question de l'utilité de déclarer cet événement abstract...

    Merci pour vos éclaircissements.

    Nara20

Discussions similaires

  1. Encore une erreur de compilation
    Par MarioNoFearS dans le forum C++
    Réponses: 3
    Dernier message: 02/06/2007, 13h05
  2. Exécutable qui génére une erreur windows
    Par jouidos dans le forum Windows Forms
    Réponses: 4
    Dernier message: 22/01/2007, 15h50
  3. .lib qui génère une erreur au link
    Par mrshadow dans le forum VC++ .NET
    Réponses: 2
    Dernier message: 19/01/2007, 10h47
  4. [Free Pascal] Aide pour comprendre une erreur de compilation
    Par SimoBenz dans le forum Free Pascal
    Réponses: 7
    Dernier message: 05/12/2006, 18h43
  5. [VB6] Problème de textbox multiligne qui génére une erreur
    Par bb62 dans le forum VB 6 et antérieur
    Réponses: 1
    Dernier message: 20/02/2006, 16h21

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