Pregunta

Tengo la siguiente clase:

class SampleClass
{
   private ArrayList mMyList;

   SampleClass()
   {
       // Initialize mMyList
   }

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

Quiero que los usuarios puedan obtener mMyList, por eso expuse el " get " Sin embargo, a través de una propiedad no quiero que se realicen cambios en el objeto (es decir, MyList.Add (new Class ());) para regresar a mi clase.

Supongo que puedo devolver una copia del objeto, pero eso puede ser lento y estoy buscando una forma que proporcione un error de tiempo de compilación informando al usuario de que no deberían esperar poder modificar el objeto devuelto. valor de la propiedad.

¿Es esto posible?

¿Fue útil?

Solución

Con un ArrayList estás bastante limitado porque no hay ninguna clase de colección no genérica de solo lectura en el BCL. La solución rápida y sucia es devolver un tipo de IEnumerable.

   public IEnumerable MyList
   {
       get { return mMyList;}
   }

En realidad, esto no evitará que alguien lance a ArrayList, pero tampoco permitirá ediciones por defecto

Puede devolver una lista de solo lectura efectiva llamando a ArrayList.ReadOnly. Sin embargo, su tipo de retorno es un ArrayList, por lo que el usuario aún podría compilar con .Add pero generaría un error de tiempo de ejecución.

Otros consejos

Use ArrayList.ReadOnly () método para construir y devolver un contenedor de solo lectura alrededor de la lista. no copiará la lista, sino que simplemente hará una envoltura de solo lectura alrededor de ella. Para obtener una verificación en tiempo de compilación, es probable que desee devolver el contenedor de solo lectura como IEnumerable como sugiere @Jared.

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

Una colección que es de solo lectura es   simplemente una colección con una envoltura   que impide modificar el   colección. Si se realizan cambios en el   colección subyacente, la de sólo lectura   la colección refleja esos cambios.

     

Este método es una operación O (1).

Reference

Solo para ampliar la respuesta de JaredPar. Como dijo, devolver el campo de respaldo real no es completamente seguro, ya que el usuario aún puede convertir dinámicamente el IEnumerable a una ArrayList .

Escribiría algo como esto para asegurarme de que no se realicen modificaciones a la lista original:

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

Otra vez, probablemente también usaría una lista genérica ( IEnumerable < T > ) para estar completamente a salvo.

Utilice una ReadOnlyCollection .

  

devuelve el nuevo ReadOnlyCollection < object > (mMyList) .

También puede hacer que el ReadOnlyCollection sea un campo, y reflejará automáticamente los cambios en la lista subyacente. Esta es la solución más eficiente.

Si sabe que mMyList solo contiene un tipo de objeto (por ejemplo, no tiene más que DateTimes), puede devolver un ReadOnlyCollection < DateTime > (o algún otro tipo) para seguridad de tipo adicional. Si está utilizando C # 3, simplemente puede escribir

  

devolver el nuevo ReadOnlyCollection < DateTime > (mMyList.OfType < DateTime > (). ToArray ())

Sin embargo, esto no se actualizará automáticamente con la lista subyacente, y también es menos eficiente (copiará la lista completa). La mejor opción es hacer de mMyList un List < T > genérico (por ejemplo, un List < DateTime > )

Debería envolver el valor de retorno en una colección de solo lectura.

Disponible desde .NET v2.0

    public ArrayList MyList { get; private set; }

Simplemente haga la propiedad como Sellada (o NotInheritable en VB.NET) y de solo lectura, como esto:

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

Tampoco olvide hacer el campo de respaldo como de solo lectura:

   private readonly ArrayList mMyList;

Pero para inicializar el valor de mMyList, debe inicializarlo SOLAMENTE en el constructor, como en este ejemplo:

public SampleClass()
{
   // Initialize mMyList
   mMyList = new ArrayList();
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top