¿Es una mala práctica modificar una Lista de esta manera?

En la Clase A (Qué generará la Lista si no está vacía):

private List<int> _myList = new List<int>
public List<int> MyList {get{return _myList;} set{_myList = value;}}

En Clase B:

public bool MyClassBMethod(stuff)
{
     //stuff
     try{
          something
     }
     catch(Exception){
         ClassA.MyList.Add(stuff);
         return false;
     }
     return true;
}

¿Editar una lista como esta es una mala práctica? ¿O está bien?

Editar: solo estoy agregando a la lista como tal cuando mi método necesita devolver algo más (bool, objeto, cadena, etc.).

preguntado el 22 de mayo de 12 a las 21:05

Me parece bien. ¿Qué te preocupa? -

¿Qué quieres decir con "así". ¿De otra clase? ¿A través de una propiedad? ¿A través del método Agregar? -

¿Es la clase A un public static ¿clase? O de qué otra manera estás accediendo MyList en la clase B? -

usar getters y setters automáticos public List<int> MyList {get;set;} No hay razón para declarar las variables públicas/privadas como en los viejos tiempos. -

Bueno, mirando tu edición... las cosas cambian. Este código es REALMENTE feo. Una de las cosas, no devuelva verdadero o falso para manejar errores, use try/catch ... -

5 Respuestas

En general, una clase debe ser responsable de administrar su propio estado interno. Al dar acceso público completo a un miembro como este, básicamente estás diciendo que la Clase A está renunciando a la responsabilidad de esa parte de su estado. No puede hacer suposiciones sobre lo que contiene _myList porque cualquiera podría cambiar eso en cualquier momento.

Si eso es bueno o no depende de cuál sea su intención, pero ciertamente va en contra de las ideas de desacoplamiento y encapsulación. Nuevamente, ya sea que usted quieres el desacoplamiento y la encapsulación dependen de usted.

Una mejor pregunta sería determinar qué tipo de desacoplamiento entre las clases A y B sería más beneficioso para su diseño, y luego podría decidir qué miembro exponer y cómo.

contestado el 22 de mayo de 12 a las 21:05

Normalmente no deberías hacer eso.

Está exponiendo una interfaz muy grande a los clientes de su clase, lo que dificulta probar que su clase funciona en todas las situaciones. ¿Qué sucede si alguien elimina valores cuando no lo espera? ¿O qué pasa si agregan un valor que está fuera de rango? No puede validarlo en el momento en que llaman al método en su List, por lo que su clase podría romperse repentinamente en algún momento posterior cuando podría ser difícil rastrear de dónde provienen los datos incorrectos.

Es mejor tener un Add método en su clase que llama a la lista Addy mantenga la lista privada. Luego, puede controlar lo que hacen sus clientes y solo exponer la funcionalidad que necesitan usar (y que ha probado).

contestado el 22 de mayo de 12 a las 21:05

No estoy de acuerdo en absoluto. Esta es una forma muy común de interactuar con listas en el marco .Net. - Ignacio Soler García

@SoMoS: ¿Puede dar un ejemplo de una clase en el marco .NET que expone un List<T> como propiedad pública? - marca byers

Colecciones observables de WPF. Siempre los estás mostrando de esta manera. - Ignacio Soler García

No es una lista sino una IList, una IEnumerable o una ICollection, en el contexto de la pregunta es lo mismo. - Ignacio Soler García

Exponiendo un IEnumerable<T> no está en absoluto lo mismo que exponer un List<T>. yo no tendria ningun problema con IEnumerable<T>, siempre que tenga sentido para la situación, por supuesto. - marca byers

Esta es una práctica bastante común. Lo que no es tan común es tener el conjunto público. Hágalo privado, inicialice la lista en el constructor A y ya está todo listo.

public ObservableCollection<int> MyPublicList {get; private set;}

WPF está lleno de declaraciones como esta.

contestado el 22 de mayo de 12 a las 21:05

Depende de si te importa si la lista está expuesta o no. Al exponer y acceder a un tipo público y concreto, está exponiendo un detalle de implementación y aumentando el acoplamiento entre la clase y sus consumidores. tu tambien estas limitando ClassALas oportunidades de hacer cumplir la coherencia de los datos, ya que los detalles de sus implementaciones ya no se encapsulan correctamente.

A veces, esto es perfectamente aceptable, a veces, no lo es.

Diría que es aceptable en los casos en que el modelo de objeto es tonto. Por tonto, quiero decir que solo contiene datos. Situaciones como esta ocurren a menudo cuando se analiza JSON/XML en objetos: las cosas están estructuradas para reflejar los datos y el comportamiento realmente no importa mucho, ya que hay muy poco. También es más aceptable si solo está hackeando una base de código pequeña y/o hay un margen limitado para el cambio, o hay muy poco comportamiento involucrado.

Sin embargo, normalmente lo evitaría.

En primer lugar, imagine que los elementos que agrega a ClassALa lista de deben ser números primos. Podría hacer cumplir fácilmente este control si escribe un AddItem() método, pero se vuelve mucho más difícil hacerlo de manera efectiva si la lista se expone públicamente.

En segundo lugar, suponga que decide cambiar la lista para que sea un diccionario. Es probable que ahora rompa los sitios de códigos de llamada (ClassB, por ejemplo), ya que anteriormente dependían de un detalle de implementación de ClassA. Si, en cambio, creó métodos llamados AddItem() y RemoveItem() o similar para ClassA, ClassB no le importaría si la implementación interna es un Conjunto, Diccionario o Lista, etc., ni se rompería cuando se realicen los cambios.

Directrices en torno a 'Puntear en las cosas' (como blah.List[3].GetProduct(3).Reviews.First()) tiene un nombre: La ley de Demeter.

El punto sobresaliente de La Ley de Deméter es:

La noción fundamental es que un objeto dado debe suponer lo menos posible sobre la estructura o las propiedades de cualquier otra cosa (incluidos sus subcomponentes).

A menudo tiene que escribir más código, pero lo aísla contra el cambio.

Respondido el 20 de junio de 20 a las 10:06

Como siempre, depende. Si la lista está destinada a ser editada fuera de la clase (es parte de la interfaz de esa clase) y todas las operaciones regulares de la lista están permitidas, está bien. Si solo se permite un subconjunto de operaciones, entonces no debe usarlo así: use una lista personalizada (o un contenedor alrededor de su lista) que aplique todas las restricciones. Por ejemplo, si la lista debe ser de solo lectura fuera de la clase, podría proporcionar una Colección de solo lectura contenedor fuera de la clase. Todo se reduce a hacer cumplir la integridad de los datos.

contestado el 22 de mayo de 12 a las 22:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.