Domanda

Ho la seguente classe:

class SampleClass
{
   private ArrayList mMyList;

   SampleClass()
   {
       // Initialize mMyList
   }

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

Voglio che gli utenti siano in grado di ottenere mMyList ed è per questo che ho esposto " get " tramite una proprietà, tuttavia non voglio che vengano apportate modifiche all'oggetto (ad esempio MyList.Add (new Class ());) per tornare alla mia classe.

Suppongo di poter restituire una copia dell'oggetto ma potrebbe essere lento e sto cercando un modo che fornisca un errore di compilazione che informi l'utente che non dovrebbero aspettarsi di essere in grado di modificare il reso valore dalla proprietà.

È possibile?

È stato utile?

Soluzione

Con una ArrayList sei abbastanza limitato perché non esiste una classe di raccolta di sola lettura non generica nel BCL. La soluzione rapida e sporca è restituire un tipo di IEnumerable.

   public IEnumerable MyList
   {
       get { return mMyList;}
   }

Questo in realtà non impedirà a nessuno di trasmettere ad ArrayList ma non consentirà nemmeno le modifiche di default

Puoi restituire un elenco di sola lettura chiamando ArrayList.ReadOnly. Tuttavia, il tipo restituito è una ArrayList, quindi l'utente sarebbe comunque in grado di compilare con .Add ma produrrebbe un errore di runtime.

Altri suggerimenti

Utilizza ArrayList.ReadOnly () metodo per costruire e restituire un wrapper di sola lettura nell'elenco. non copia l'elenco, ma crea semplicemente un wrapper di sola lettura. Per ottenere il controllo in fase di compilazione, probabilmente si desidera restituire il wrapper di sola lettura come IEnumerable come suggerisce @Jared.

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

Una raccolta di sola lettura è   semplicemente una collezione con un involucro   che impedisce la modifica di   collezione. Se vengono apportate modifiche a   raccolta sottostante, la sola lettura   raccolta riflette tali cambiamenti.

     

Questo metodo è un'operazione O (1).

Riferimento

Solo per espandere la risposta di JaredPar. Come ha detto, la restituzione del campo di supporto effettivo non è completamente sicura, poiché l'utente è ancora in grado di eseguire il cast dinamico di IEnumerable in un ArrayList .

Scriverei qualcosa del genere per essere sicuro che non vengano apportate modifiche all'elenco originale:

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

Di nuovo, probabilmente userei anche un elenco generico ( IEnumerable < T > ) per essere completamente sicuro.

Utilizza un ReadOnlyCollection .

  

restituisce il nuovo oggetto ReadOnlyCollection < object > (mMyList) .

Puoi anche rendere ReadOnlyCollection un campo, che rifletterà automaticamente le modifiche nell'elenco sottostante. Questa è la soluzione più efficiente.

Se sai che mMyList contiene solo un tipo di oggetto (ad esempio, non ha altro che DateTimes), puoi restituire un ReadOnlyCollection < DateTime > (o un altro tipo) per ulteriore sicurezza del tipo. Se stai usando C # 3, puoi semplicemente scrivere

  

restituisce il nuovo ReadOnlyCollection < DateTime > (mMyList.OfType < DateTime > (). ToArray ())

Tuttavia, questo non si aggiorna automaticamente con l'elenco sottostante ed è anche meno efficiente (copierà l'intero elenco). L'opzione migliore è fare di mMyList un Elenco < T > generico (ad es. Un Elenco < DateTime > )

Dovresti racchiudere il valore restituito in una raccolta di sola lettura.

Disponibile da .NET v2.0

    public ArrayList MyList { get; private set; }

Rendi la proprietà come Sealed (o NotInheritable in VB.NET) e di sola lettura, in questo modo:

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

Inoltre, non dimenticare di rendere il campo di supporto di sola lettura:

   private readonly ArrayList mMyList;

Ma per inizializzare il valore di mMyList, è necessario inizializzarlo SOLO nel costruttore, come in questo esempio:

public SampleClass()
{
   // Initialize mMyList
   mMyList = new ArrayList();
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top