27 votes

C# retourne une variable en lecture seule à partir de get ; set ;

Je jure que j'ai vu un exemple de cela mais j'ai cherché sur Google et je ne l'ai pas trouvé.

J'ai une classe qui a une référence à un objet et j'ai besoin d'avoir une méthode GET ; pour celui-ci. Mon problème est que je ne veux pas que quelqu'un puisse le manipuler, c'est-à-dire que je veux qu'il obtienne une version en lecture seule de l'objet (je dois pouvoir le modifier à l'intérieur de ma classe).

Merci

45voto

Jon Skeet Points 692016

Non, il n'y a aucun moyen de le faire. Par exemple, si vous renvoyez un List<string> (et il n'est pas immuable) alors les appelants sera être en mesure d'ajouter des entrées.

Le moyen normal de contourner ce problème est de renvoyer un wrapper immuable, par ex. ReadOnlyCollection<T> .

Pour les autres types mutables, vous devrez peut-être cloner la valeur avant de la renvoyer.

Notez que le simple fait de renvoyer une vue d'interface immuable (par exemple, renvoyer IEnumerable<T> au lieu de List<T> ) n'empêchera pas un appelant de revenir au type mutable et de muter.

EDIT : Notez qu'en dehors de toute autre chose, ce type de préoccupation est l'une des raisons pour lesquelles les types immuables facilitent le raisonnement sur le code :)

6voto

Anton Gogolev Points 59794

Renvoie une référence à une interface dépouillée :

 interface IFoo
   string Bar { get; }

 class ClassWithGet
   public IFoo GetFoo(...);

3voto

Jamie Ide Points 28680

Ce n'est pas possible. Les accesseurs Get et Set des types de référence obtiennent et définissent la référence à l'objet. Vous pouvez empêcher les modifications de la référence en utilisant un setter privé (ou interne), mais vous ne pouvez pas empêcher les modifications de l'objet lui-même s'il est exposé par un getter.

3voto

justlost Points 118

Si l'objet n'est pas trop compliqué/extensif, écrivez une enveloppe autour de lui.

par exemple :

class A {
    public string strField = 'string';
    public int intField = 10;
}

class AWrapper {
    private A _aObj;

    public AWrapper(A aobj) {
      _aObj = A;
    }

    public string strField {
         get {
            return _aObj.strField;
         }
    }

    public int intField {
         get {
            return _aObj.intField;
         }
    }
}

Il ne vous reste plus qu'à donner à votre code client une instance de la classe AWrapper afin qu'il ne puisse utiliser que ce que vous lui permettez de voir.

Cela peut devenir un peu compliqué et ne pas être adapté si votre classe de base n'est pas figée, mais pour la plupart des situations simples, cela peut faire l'affaire. Je pense que cela s'appelle un modèle de façade (mais ne me citez pas sur ce point =) ).

1voto

Matt Points 2085

Votre question ressemble à ce que vous recherchez :

public PropertyName { get; private set; }

Mais étant donné les réponses données jusqu'à présent, je ne suis pas sûr d'interpréter correctement votre question. D'ailleurs, qui suis-je pour remettre en question Jon Skeet ? :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X