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 :

Accesseurs en c#


Sujet :

C#

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Février 2008
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2008
    Messages : 9
    Points : 7
    Points
    7
    Par défaut Accesseurs en c#
    Bonjour à tous.

    Issu du monde C++ j'ai l'habitude de faire des accesseurs get qui retournent une référence constante et des accesseurs set qui prent comme paramètre une référence constante.
    De sorte que le get permet d'acceder directement à un objet avec une sémantique de valeur sans création d'objet temporaire (puisque le const protège contre les modifications à l'exterieur de la classe).
    Et de sorte que le set permet d'assigner la valeur reçue sans création, là non plus, d'objet temporaire, éventuellement avec la surcharge de l'opérateur= de la classe de l'objet à assigner.

    Mais en c# pas de const et pas de surcharge de l'opérateur=. La solution me semble de faire comme ce qui suit:

    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
     
    namespace csq001
    {
     
        // Classe à sémantique de valeur.
        // (pas pas une Struct !! sinon le problème ne se pose plus)
        class Data
        {
            public Data() {}
            public Data(int aValue) { mValue = aValue; }
            public Data(Data aData) { mValue = aData.mValue;  }
     
            private int mValue = 0;
        }
     
        // Class qui presente une valeur (set)
        class Presenter
        {
            public Presenter(int aValue) { mData = new Data(aValue); }
     
            public Data Value
            {
                // Accesseur
                // Création d'une copie pour protéger
                // l'attribut privé.
                get { return new Data(mData); }
            }
     
            private Data mData;
        }
     
        // Classe a qui on fournit une valeur (get)
        class User
        {
            public Data Value
            {
                // Accesseur
                // Création d'un copie pour protéger
            // le fournisseur et remplacer l'ancienne instance par la nouvelle.
                set { mData = new Data(value); }
            }
     
            private Data mData = new Data();
        }
     
     
     
        class Program
        {
            static void Main(string[] args)
            {
                Presenter lPresenter = new Presenter(27);
                User lUser = new User();
                // A ce point
                // lPresenter.mData.mValue vaut 27
                // lUser.mData.mValue vaut 0
                lUser.Value = lPresenter.Value;
                // A ce point
                // lPresenter.mData.mValue vaut 27
                // lUser.mData.mValue vaut 27
                // C'est ce qui est voulu.
            }
        }
    }
    Mais l'accesseur get créé un objet de classe Data dont la durée de vie est très temporaire. Et l'accesseur set crée un objet de classe Data qui remplace le lUser.mData précédent.

    Bilan 2 duplications d'objet et 2 objets à traiter par le garbage collector, ce que je n'aurai jamais écrit en C++.

    Comment faire mieux ? Est-ce nécessaire de faire mieux ? Comment gère t'on cette problématique récurrente en C# (J'imagine qu'il y a le même problème en Java) ?

    Merci d'avance.

  2. #2
    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 : 43
    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
    Points : 39 753
    Points
    39 753
    Par défaut


    J'ai pas tout compris à ton histoire, mais j'ai l'impression que tu te compliques la vie inutilement... Qu'est-ce que tu appelles "sémantique de valeur" ? tu veux que lors de l'affectation de la propriété Value, la valeur conservée soit une copie et non une référence, c'est ça ? Dans ce cas pourquoi ne pas déclarer Data comme une struct ?

    Il faudrait que tu expliques plus précisément ton besoin pour qu'on puisse t'aider, parce que là ce n'est pas très clair

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    612
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 612
    Points : 338
    Points
    338
    Par défaut
    je crois te comprendre

    enfait tu raison un peut trop en "C/C++"
    si j'ai bien compris ton extrait de code tu fait des news pour que le futur utilisateur ne puisse pas modifier la variable private?

    par definition une variable private n'est accessible(et donc modifiable) uniquement dans la classe elle meme. il faut donc fair appel a un accesseurs pour la lire ou la modifier. si ton accesseur ne possede pas de set alors aucun risque! readonly à 200%!!

    ton code deviens donc

    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
    35
    36
    37
    38
    39
    40
    41
    namespace csq001
    {
        public class Data
        {
            private int mValue = 0;
     
            public Data() {}
            public Data(int aValue) { mValue = aValue; }
            public Data(Data aData) { mValue = aData.mValue; }
        }
     
        public class Presenter
        {
            private Data mData;
            public Data Value
            {
                get { return mData; }
            }
     
            public Presenter(int aValue) { mData = new Data(aValue); }
        }
     
        public class User
        {
            private Data mData = new Data();
            public Data Value
            {
                set { mData = value; }
            }
        }
     
        class Program
        {
            static void Main(string[] args)
            {
                Presenter lPresenter = new Presenter(27);
                User lUser = new User();
                lUser.Value = lPresenter.Value;
            }
        }
    }
    comme tu peut le voir j'ai ajouter des "public" dans la definition des classe, il vaut mieu etre explicite


    C# a des notions asser variante, je te conseil de survoler(suivant ton experience) un petit tuto ou deux sur les principaux fondement en C# qui peuvent changer par rapport au C

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

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    Il n'y a pas de const-correctness en C#. Si tu refiles une référence vers un objet, alors l'appelant peut faire tout et n'importe quoi avec.

    Une solution plus "C#, java", serait de définir une interface ne contenant que des get, de faire implémenter cette interface à ton objet métier, et de ne renvoyer cet objet que sous la forme de l'interface.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    interface ICustomer { int Id {get;} }
    class Customer : ICustomer { public int Id {get; set; } }
     
    class Machin
    {
      private Customer c = new Customer();
      public ICustomer LeClient { return c; }
    }
     
    Machin m = new Machin();
    m.LeClient.Id = 9; // erreur !
    C'est contournable en recastant LeClient en Customer, mais c'est similaire à la possibilité offerte par C++ de "dé-const-er" une variable const.

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Février 2008
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2008
    Messages : 9
    Points : 7
    Points
    7
    Par défaut
    La solution présentée par Guulh est intéressante, mais si faut la mettre en oeuvre pour chaque type de membre à proteger... ça devient vite lourd.

    La construction par recopie ou le clonage du membre à protéger est plus triviale mais plus gourmande en CPU.

  6. #6
    Futur Membre du Club
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Février 2008
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2008
    Messages : 9
    Points : 7
    Points
    7
    Par défaut
    Citation Envoyé par TheBlackReverand Voir le message
    je crois te comprendre

    enfait tu raison un peut trop en "C/C++"
    si j'ai bien compris ton extrait de code tu fait des news pour que le futur utilisateur ne puisse pas modifier la variable private?

    par definition une variable private n'est accessible(et donc modifiable) uniquement dans la classe elle meme. il faut donc fair appel a un accesseurs pour la lire ou la modifier. si ton accesseur ne possede pas de set alors aucun risque! readonly à 200%!!
    Non, ça marche pas. Tu ne peut pas changer l'objet membre mais tu peux y acceder (meme en modification).

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

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    Citation Envoyé par feaxfiwe Voir le message
    La construction par recopie ou le clonage du membre à protéger est plus triviale mais plus gourmande en CPU.
    Ben c'est surtout qu'on est plus lié à l'objet d'origine, là. Si jamais ton Data est modifié, il faut le redemander au Presenter.

  8. #8
    Futur Membre du Club
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Février 2008
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2008
    Messages : 9
    Points : 7
    Points
    7
    Par défaut
    Citation Envoyé par Guulh Voir le message
    Ben c'est surtout qu'on est plus lié à l'objet d'origine, là. Si jamais ton Data est modifié, il faut le redemander au Presenter.
    C'est ce que je voulais, sauf que l'interaction entre le Presenter et le User (de mon exemple) nécessite 2 instanciation et 2 objets à détruire, alors qu'en C++ on avait simplement l'utilisation d'une référence (entre le get et le set) et une affectation (du membre de User).

    Je voyais aussi la possibilité d'utiliser des objets immuables (comme String), parce que même si plusieurs instances sont associées à un tel objet, aucune ne peut le modifier.

    D'ailleurs, microsoft est un peu voleur dans le MSDN, car les exemples de propriétés qu'il donne utilisent toujours des types simples (enfin des structs) qui sont toujours dupliqués puisque gérés en pile ou des objets String (qui de par leur coté immuable n'est pas concerné par le problème). En revanche, sur les objets instances de classes ... pas d'exemple, pas de consigne

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

Discussions similaires

  1. Outils pour creer les accesseurs et les mutateurs
    Par MarieMtl dans le forum MFC
    Réponses: 3
    Dernier message: 03/10/2005, 17h03
  2. Réponses: 6
    Dernier message: 02/09/2005, 20h36
  3. [Language][constructeur] - attributs ou accesseur
    Par grand's dans le forum Langage
    Réponses: 6
    Dernier message: 26/04/2005, 08h47
  4. [C#] [VS.NET] Peut on faire un accesseur sur objets?
    Par Designotik dans le forum Windows Forms
    Réponses: 3
    Dernier message: 06/01/2005, 21h56
  5. [NetBeans 4.0] Accesseur?
    Par Kaor dans le forum NetBeans
    Réponses: 2
    Dernier message: 20/12/2004, 14h22

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