net - set c#
"Solo lectura" Property Accessor en C# (8)
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 lo que expuse el "get" a través de una propiedad, pero no quiero que se realicen cambios en el objeto (es decir, MyList.Add (new Class ());) para realizar su De regreso 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 en tiempo de compilación informando al usuario de que no deberían esperar poder modificar el valor devuelto desde el Propiedad.
es posible?
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 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.
Debe ajustar 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 No se puede heredar en VB.NET) y de solo lectura, como esto:
public sealed readonly ArrayList MyList
{
get { return mMyList;}
}
Además, no 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();
}
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 IEnumerable
dinámicamente el IEnumerable
a un ArrayList
.
Escribiría algo como esto para asegurarme de que no se hagan modificaciones a la lista original:
public IEnumerable MyList
{
get
{
foreach (object o in mMyList)
yield return o;
}
}
Por otra parte, probablemente también usaría una lista genérica ( IEnumerable<T>
) para estar completamente segura.
Use el método ArrayList.ReadOnly() 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 la 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 un contenedor que evita la modificación de la colección. Si se realizan cambios en la colección subyacente, la colección de solo lectura refleja esos cambios.
Este método es una operación O (1).
Utilice un ReadOnlyCollection
.
return new ReadOnlyCollection<object>(mMyList)
.
También puede hacer que ReadOnlyCollection
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 nada 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
return new 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 que mMyList sea una List<T>
genérica List<T>
(por ejemplo, una List<DateTime>
)