Vamos a decir que tengo una Car
clase:
public class Car
{
public string Engine { get; set; }
public string Seat { get; set; }
public string Tires { get; set; }
}
Digamos que estamos haciendo un sistema sobre un estacionamiento, voy a usar una gran parte de la Car
clase, por lo que hacemos una CarCollection
clase, puede tener algunos métodos adicionales como FindCarByModel
:
public class CarCollection
{
public List<Car> Cars { get; set; }
public Car FindCarByModel(string model)
{
// code here
return new Car();
}
}
Si estoy haciendo una clase ParkingLot
, ¿cuál es la mejor práctica?
Opción 1:
public class ParkingLot
{
public List<Car> Cars { get; set; }
//some other properties
}
Opcion 2:
public class ParkingLot
{
public CarCollection Cars { get; set; }
//some other properties
}
¿Es incluso una buena práctica crear uno ClassCollection
de otro Class
?
CarCollection
lugar de unList<Car>
alrededor? Especialmente dado que CarCollection no extiende la clase de la Lista de respaldo, ni siquiera implementa la interfaz de la Colección (estoy seguro de que C # tiene cosas similares).public class CarCollection
no implementa IList o ICollection, etc., por lo tanto, no puede pasarlo a algo que esté bien con una lista. Afirma como parte de su nombre que es una colección, pero no implementa ninguno de esos métodos.CarColection
con unaTotalTradeValue
propiedad en él. DDD no es la única forma de diseñar sistemas, solo lo señala como una opción.Respuestas:
Antes de los genéricos en .NET, era una práctica común crear colecciones 'escritas' para que tuviera
class CarCollection
etc. para cada tipo que necesitara agrupar. En .NET 2.0 con la introducción de Generics,List<T>
se introdujo una nueva clase que le ahorra tener que crear,CarCollection
etc., como puede crearList<Car>
.La mayoría de las veces, encontrará que
List<T>
es suficiente para sus propósitos, sin embargo, puede haber ocasiones en que desee tener un comportamiento específico en su colección, si cree que este es el caso, tiene un par de opciones:List<T>
por ejemplopublic class CarCollection { private List<Car> cars = new List<Car>(); public void Add(Car car) { this.cars.Add(car); }}
public class CarCollection : CollectionBase<Car> {}
Si opta por el enfoque de encapsulación, como mínimo debe exponer el enumerador para que lo declare de la siguiente manera:
Sin hacer eso, no puedes hacer una
foreach
sobre la colección.Algunas razones por las que puede querer crear una colección personalizada son:
IList<T>
oICollection<T>
¿Es una buena práctica? bueno, eso depende de por qué lo está haciendo, si es, por ejemplo, una de las razones que he enumerado anteriormente, entonces sí.
Microsoft lo hace con bastante regularidad, aquí hay algunos ejemplos bastante recientes:
En cuanto a sus
FindBy
métodos, estaría tentado de ponerlos en métodos de extensión para que puedan usarse contra cualquier colección que contenga automóviles:Esto separa la preocupación de consultar la colección de la clase que almacena los autos.
fuente
ClassCollection
incluso los métodos de agregar, eliminar y actualizar, agregando un nuevoCarCRUD
que encapsulará todos estos métodos ...CarCRUD
extensión, ya que forzar su uso sería difícil, la ventaja de poner la lógica cruda personalizada en la clase de colección es que no hay forma de evitarla. Además, es posible que no le importe la lógica de búsqueda en el ensamblado central dondeCar
se declaran, etc., que podría ser una actividad exclusiva de la IU.No. La creación de
XXXCollection
clases pasó de moda con la llegada de los genéricos en .NET 2.0. De hecho, existe la ingeniosaCast<T>()
extensión LINQ que la gente usa actualmente para sacar cosas de esos formatos personalizados.fuente
ClassCollection
? ¿Es una buena práctica ponerlos en la página principalClass
?FindCarByModel
método, eso tiene sentido como un método en su repositorio, que es un poco más complejo que solo unaCar
colección.A menudo es útil tener métodos orientados al dominio para buscar / dividir colecciones, como en el ejemplo de FindByCarModel anterior, pero no hay necesidad de recurrir a la creación de clases de colección de contenedor. En esta situación, normalmente crearé un conjunto de métodos de extensión.
Agrega tantos filtros o métodos de utilidad a esa clase como desee, y puede usarlos en cualquier lugar que tenga
IEnumerable<Car>
, lo que incluye cualquier cosaICollection<Car>
, matricesCar
,IList<Car>
etc.Dado que nuestra solución de persistencia tiene un proveedor LINQ, con frecuencia también crearé métodos de filtro similares que operan y regresan
IQueryable<T>
, para que también podamos aplicar estas operaciones al repositorio.El idioma de .NET (bueno, C #) ha cambiado mucho desde 1.1. Mantener clases de colección personalizadas es una molestia, y gana poco al heredar de
CollectionBase<T>
lo que no obtiene con la solución del método de extensión si todo lo que necesita es un filtro específico de dominio y métodos de selección.fuente
Creo que la única razón para crear una clase especial para mantener una colección de otros elementos debería ser cuando se le agrega algo de valor, algo más que simplemente encapsular / heredar de una instancia
IList
u otro tipo de colección.Por ejemplo, en su caso, agregue una función que devolvería sublistas de automóviles estacionados en espacios de lotes pares / desiguales ... E incluso entonces ... tal vez solo si se reutiliza a menudo, porque si solo toma una línea con un bonito LinQ funciona y se usa solo una vez, ¿cuál es el punto? BESO !
Ahora, si planea ofrecer muchos métodos de clasificación / búsqueda, entonces sí, creo que esto podría ser útil porque aquí es donde deberían pertenecer, en esa clase de colección especial. Esta también es una buena manera de "ocultar" las complejidades de algunas consultas de "búsqueda" o cualquier cosa que pueda hacer en un método de clasificación / búsqueda.
fuente
Class
Prefiero ir con la siguiente opción, para que pueda agregar su método a la colección y usar la ventaja de la lista.
y luego puedes usarlo como C # 7.0
O puedes usarlo como
- Versión genérica gracias al comentario de @Bryan
y luego puedes usarlo
fuente