Question

J'ai la classe suivante:

class SampleClass
{
   private ArrayList mMyList;

   SampleClass()
   {
       // Initialize mMyList
   }

   public ArrayList MyList
   {
       get { return mMyList;}
   }
}

Je souhaite que les utilisateurs puissent obtenir mMyList, raison pour laquelle j’ai exposé le "get". via une propriété, mais je ne veux pas que les modifications apportées à l’objet (par exemple, MaListe.Add (new Class ());); pour revenir dans ma classe.

Je suppose que je peux renvoyer une copie de l'objet, mais que cela peut être lent et que je cherche un moyen de fournir une erreur lors de la compilation, informant l'utilisateur qu'il ne devrait pas s'attendre à pouvoir modifier l'objet retourné. valeur de la propriété.

Est-ce possible?

Était-ce utile?

La solution

Avec un ArrayList, vous êtes assez limité car il n'y a pas de classe de collection non générique en lecture seule dans la BCL. La solution rapide et incorrecte consiste à renvoyer un type IEnumerable.

   public IEnumerable MyList
   {
       get { return mMyList;}
   }

Cela n'empêchera pas réellement quelqu'un de se lancer dans ArrayList, mais cela ne permettra pas non plus les modifications par défaut

Vous pouvez renvoyer une liste en lecture seule efficace en appelant ArrayList.ReadOnly. Cependant, son type de retour est une ArrayList afin que l'utilisateur puisse toujours compiler avec .Add, mais cela produirait une erreur d'exécution.

Autres conseils

Utilisez le ArrayList.ReadOnly () méthode pour construire et retourner un wrapper en lecture seule autour de la liste. il ne copie pas la liste, mais crée simplement un wrapper en lecture seule autour de celle-ci. Pour obtenir une vérification au moment de la compilation, vous voudrez probablement renvoyer le wrapper en lecture seule comme indiqué par IEnumerable, comme le suggère @Jared.

public IEnumerable MyList
{
     get { return ArrayList.ReadOnly(mMyList); }
}
  

Une collection en lecture seule est   simplement une collection avec un wrapper   qui empêche de modifier le   collection. Si des modifications sont apportées à la   collection sous-jacente, la lecture seule   collection reflète ces changements.

     

Cette méthode est une opération O (1).

Référence

Juste pour développer la réponse de JaredPar. Comme il l'a dit, renvoyer le champ de sauvegarde actuel n'est pas totalement sûr, car l'utilisateur peut toujours rediffuser dynamiquement IEnumerable en ArrayList .

J'écrirais quelque chose comme ceci pour m'assurer qu'aucune modification ne soit apportée à la liste d'origine:

public IEnumerable MyList
{
    get
    {
         foreach (object o in mMyList)
             yield return o;
    }
}

Dans ce cas également, j'utiliserais probablement une liste générique ( IEnumerable < T > ) pour être totalement sûrs en ce qui concerne la saisie.

Utilisez une ReadOnlyCollection .

  

retourne le nouveau ReadOnlyCollection < objet > (mMyList) .

Vous pouvez également définir le champ ReadOnlyCollection pour qu'il reflète automatiquement les modifications apportées à la liste sous-jacente. C’est la solution la plus efficace.

Si vous savez que mMyList ne contient qu'un seul type d'objet (par exemple, il n'a rien d'autre que DateTimes), vous pouvez renvoyer une ReadOnlyCollection < DateTime > (ou un autre type) pour une sécurité de type supplémentaire. Si vous utilisez C # 3, vous pouvez simplement écrire

  

renvoie le nouveau ReadOnlyCollection < DateTime > (mMyList.OfType < DateTime > (). ToArray ())

Cependant, cela ne se mettra pas automatiquement à jour avec la liste sous-jacente, et sera également moins efficace (cela copiera toute la liste). La meilleure option consiste à faire de mMyList un liste générique < T > (par exemple, une liste < DateTime > )

.

Vous devez envelopper la valeur de retour dans une collection en lecture seule.

Disponible à partir de .NET v2.0

    public ArrayList MyList { get; private set; }

Faites en sorte que la propriété soit Sealed (ou NotInheritable dans VB.NET) et en lecture seule, comme ceci:

   public sealed readonly ArrayList MyList
   {
       get { return mMyList;}
   }

N'oubliez pas non plus de définir le champ de sauvegarde en lecture seule:

   private readonly ArrayList mMyList;

Mais pour initialiser la valeur de mMyList, vous devez l'initialiser UNIQUEMENT dans le constructeur, comme dans cet exemple:

public SampleClass()
{
   // Initialize mMyList
   mMyList = new ArrayList();
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top