que - public list c#
¿Hay una interfaz de colección.NET que impida agregar objetos? (7)
¿Podría simplemente darles un objeto que siempre devuelva un enumerador que puedan usar para acceder a la estructura?
Tengo una clase que mantiene la lista de objetos de otra clase. Lista de objetos es una propiedad pública. Me gustaría evitar que los usuarios agreguen y eliminen objetos directamente en una lista como esta:
MyObject.MyListProperty.Add(object);
En su lugar, quiero que utilicen un método que internamente realice algún procesamiento y luego agregue el objeto a la lista.
Tengo algunas ideas:
- crear descendiente de
List<T>
y anular agregar y eliminar - devuelva una copia nueva de la lista a través de la propiedad getter (la lista es relativamente corta, no más de 30 objetos)
¿Hay alguna interfaz de colección que no tenga Agregar o quitar?
Editar:
Voy a ir con ReadOnlyCollection<T>
. El motivo es que la colección ajustada se puede actualizar y los cambios serán visibles inmediatamente en el objeto de solo lectura (consulte los ejemplos de código de MSDN para ReadOnlyCollection<T>
y AsReadOnly()
). Esto permite que la lista de solo lectura se cree solo una vez.
El problema con IEnumerable
es que el objeto puede volver a convertirse en la List<T>
original List<T>
y luego manipularse directamente.
Fuera de la caja, solo IEnumerable<T>
proporcionará esto sin exponer ningún método público de Add
y Remove
que pueda engañar al cliente para que obtenga una excepción de tiempo de ejecución.
Si desea que su API pública indique explícitamente que la colección es de solo lectura y necesita un indexador, tendrá que escribir su propio envoltorio alrededor de la List<T>
existente List<T>
o T[]
.
ICollection (la versión no genérica) solo obtuvo IEnumerable + Count
Puede usar ReadOnlyCollection<T> : envuelva su colección con esto y devuelva ReadOnlyCollection
a los usuarios de su clase:
return new ReadOnlyCollection(innerCollection);
O usando el método AsReadOnly
de la clase List<T>
:
return innerCollection.AsReadOnly();
La interfaz IEnumerable hará lo que necesite, ya que solo tiene un miembro GetEnumerator()
, que solo le permitirá iterar sobre los elementos.
Realmente no responde su pregunta, pero es una información útil si decide implementar una de sus dos ideas: puede usar ToArray para crear una copia y devolver una matriz.
O puede hacer algo como esto: http://en.csharp-online.net/CSharp_Generics_Recipes%E2%80%94Making_Read-Only_Collections_the_Generic_Way
Su opción más fácil sería exponer su lista como uno de los siguientes IEnumerable de la IEnumerable ReadOnlyCollection<T> IEnumerable , ICollection través de una propiedad pública.
Por lo tanto, puede crear su propio type
de lista que exponga sus Items
como uno de los anteriores pero tiene un método interno para agregar, por ejemplo,
public class MyList<MyType>
{
private List<MyType> items;
public MyList()
{
items = new List<MyType>();
}
public IEnumerable Items { get { return items.AsEnumerable(); } }
public Add(MyType item)
{
// do internal processing
items.Add(item);
}
}
Tal AsReadOnly() método AsReadOnly() hará el truco para entregar una instancia de solo lectura al público.
De lo contrario, IEnumerable<T>
no tiene Add
ni Remove
, por lo que puede hacer algo como:
private List<int> _myList;
public IEnumerable<int> MyList
{
get
{
return this._myList.ToList();
}
}
Preferiría ir a IEnumerable<T>
(+ copia) que a ReadOnlyCollection<T>
, porque: los cambios en su lista base (desde la que se crea su colección de solo lectura) aparecerán inmediatamente en su instancia de la lectura única colección Esto puede causar problemas de bloqueo y de error :)