Question

Je travaille à la création d'une classe immuable.
J'ai marqué toutes les propriétés en lecture seule.

J'ai une liste d'éléments dans la classe.
Cependant, si la propriété est en lecture seule, la liste peut être modifiée.

Exposer le IEnumerable de la liste le rend immuable.
Je voulais savoir quelles sont les règles de base à suivre pour rendre une classe immuable.

Était-ce utile?

La solution

Je pense que vous êtes sur la bonne voie -

  • toutes les informations injectées dans la classe doivent être fournies dans le constructeur
  • toutes les propriétés doivent être des accesseurs uniquement
  • si une collection (ou un tableau) est transmise au constructeur, il convient de la copier pour empêcher l'appelant de la modifier ultérieurement
  • si vous souhaitez retourner votre collection, renvoyez une copie ou une version en lecture seule (par exemple, à l'aide de ArrayList.ReadOnly ou similaire - vous pouvez combiner cela avec le point précédent et stocke une copie en lecture seule à renvoyer lorsque les appelants y accèdent), renvoient un énumérateur ou utilisez une autre méthode / propriété permettant un accès en lecture seule à la collection
  • N'oubliez pas que vous pouvez toujours avoir l'apparence d'une classe mutable si l'un de vos membres est mutable. Si tel est le cas, vous devez copier tout état que vous souhaitez conserver et éviter de renvoyer des objets mutables entiers, à moins que vous les copiez avant de les redonner à l'appelant - une autre option consiste à renvoyer uniquement les " sections " immuables; de l'objet mutable - merci à @Brian Rasmussen de m'avoir encouragé à développer ce point

Autres conseils

Pour être immuable, toutes vos propriétés et tous vos champs doivent être en lecture seule. Et les éléments de toute liste doivent eux-mêmes être immuables.

Vous pouvez créer une propriété de liste en lecture seule comme suit:

public class MyClass
{
    public MyClass(..., IList<MyType> items)
    {
        ...
        _myReadOnlyList = new List<MyType>(items).AsReadOnly();
    }

    public IList<MyType> MyReadOnlyList
    {
        get { return _myReadOnlyList; }
    }
    private IList<MyType> _myReadOnlyList

}

N'oubliez pas non plus que:

public readonly object[] MyObjects;

n'est pas immuable, même s'il est marqué avec le mot clé readonly. Vous pouvez toujours modifier les références / valeurs de tableaux individuels par un accesseur d'index.

Utilisez la ReadOnlyCollection classe. Il est situé dans le System.Collections.ObjectModel espace de noms.

Sur tout ce qui retourne votre liste (ou dans le constructeur), définissez la liste comme une collection en lecture seule.

using System.Collections.ObjectModel;

...

public MyClass(..., List<ListItemType> theList, ...)
{
    ...
    this.myListItemCollection= theList.AsReadOnly();
    ...
}

public ReadOnlyCollection<ListItemType> ListItems
{
     get { return this.myListItemCollection; }
}

Une autre option consisterait à utiliser un modèle de visiteur au lieu d'exposer les collections internes.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top