Disons que j'ai un Car
cours:
public class Car
{
public string Engine { get; set; }
public string Seat { get; set; }
public string Tires { get; set; }
}
Disons que nous construisons un système sur un parking, je vais utiliser beaucoup de Car
cours, alors nous faisons un CarCollection
cours, il peut avoir quelques méthodes supplémentaires telles que FindCarByModel
:
public class CarCollection
{
public List<Car> Cars { get; set; }
public Car FindCarByModel(string model)
{
// code here
return new Car();
}
}
Si je fais un cours ParkingLot
, quelle est la meilleure pratique?
Option 1:
public class ParkingLot
{
public List<Car> Cars { get; set; }
//some other properties
}
Option 2:
public class ParkingLot
{
public CarCollection Cars { get; set; }
//some other properties
}
Est-ce même une bonne pratique de créer un ClassCollection
autre Class
?
CarCollection
cercle plutôt que d'unList<Car>
cercle? D'autant plus que CarCollection n'allonge pas la classe Liste de sauvegarde, ni n'implémente l'interface Collection (je suis sûr que C # a des choses similaires).public class CarCollection
n'implémente pas IList ou ICollection, etc ... vous ne pouvez donc pas le transmettre à quelque chose qui convient à une liste. Il affirme dans son nom qu'il s'agit d'une collection, mais n'implémente aucune de ces méthodes.CarColection
avec uneTotalTradeValue
propriété dessus. DDD n'est pas le seul moyen de concevoir des systèmes, il suffit de l'indiquer en option.Réponses:
Avant les génériques dans .NET, il était courant de créer des collections 'dactylographiées' afin que vous ayez
class CarCollection
etc pour chaque type que vous aviez besoin de grouper. Dans .NET 2.0, avec l'introduction de Generics, une nouvelle classe aList<T>
été introduite, ce qui vous évite d'avoir à créerCarCollection
etc. comme vous pouvez le créerList<Car>
.La plupart du temps, vous constaterez que cela
List<T>
suffit pour vos besoins, mais il peut arriver que vous souhaitiez avoir un comportement spécifique dans votre collection. Si vous pensez que cela est le cas, vous avez plusieurs options:List<T>
par exemplepublic class CarCollection { private List<Car> cars = new List<Car>(); public void Add(Car car) { this.cars.Add(car); }}
public class CarCollection : CollectionBase<Car> {}
Si vous optez pour l’encapsulation, vous devez au moins exposer l’énumérateur afin de le déclarer comme suit:
Sans cela, vous ne pouvez pas en faire
foreach
plus sur la collection.Certaines des raisons pour lesquelles vous pouvez créer une collection personnalisée sont les suivantes:
IList<T>
ouICollection<T>
Est-ce une bonne pratique? Cela dépend de la raison pour laquelle vous le faites. Si c’est par exemple l’une des raisons que j’ai énumérées ci-dessus, alors oui.
Microsoft le fait assez régulièrement, voici quelques exemples assez récents:
En ce qui concerne vos
FindBy
méthodes, je serais tenté de les mettre en extension afin qu’elles puissent être utilisées contre toute collection contenant des voitures:Ceci sépare le souci d'interroger la collection de la classe qui stocke les voitures.
la source
ClassCollection
méthodes même pour les méthodes d'ajout, de suppression et de mise à jour, en ajoutant une nouvelleCarCRUD
qui encapsulera toutes ces méthodes ...CarCRUD
extension car il serait difficile d'appliquer son utilisation. L'avantage de mettre la logique crud personnalisée dans la classe de collection est qu'il n'y a aucun moyen de la contourner. En outre, vous ne vous souciez peut-être pas de la logique de recherche dans l'assembly principal dans lequelCar
etc sont déclarés, ce qui peut être une activité de l'interface utilisateur uniquement.Non. La création de
XXXCollection
classes est tombée en désuétude avec l'avènement des génériques dans .NET 2.0. En fait, il existe l'Cast<T>()
extension astucieuse LINQ que les gens utilisent de nos jours pour extraire des contenus de ces formats personnalisés.la source
ClassCollection
? Est-ce une bonne pratique de les mettre sur le marchéClass
?FindCarByModel
méthode , par exemple, cela fait sens en tant que méthode sur votre référentiel, ce qui est légèrement plus complexe qu'une simpleCar
collection.Il est souvent pratique de disposer de méthodes orientées domaine pour rechercher / découper des collections, comme dans l'exemple de FindByCarModel ci-dessus, mais il n'est pas nécessaire de recourir à la création de classes de collection wrapper. Dans cette situation, je vais maintenant généralement créer un ensemble de méthodes d'extension.
Vous ajoutez autant de méthodes de filtrage ou d’utilitaires à cette classe que vous le souhaitez, et vous pouvez les utiliser n’importe où vous avez
IEnumerable<Car>
, y compris tout type deICollection<Car>
tableauxCar
,IList<Car>
etc.Étant donné que notre solution de persistance a un fournisseur LINQ, je crée fréquemment des méthodes de filtrage similaires qui fonctionnent sur et qui renvoient
IQueryable<T>
afin que nous puissions également appliquer ces opérations au référentiel.L'idiome de .NET (enfin, C #) a beaucoup changé depuis la 1.1. La maintenance de classes de collection personnalisées est une tâche ardue, et vous n’avez que peu à gagner en héritant de
CollectionBase<T>
la solution de méthode d’extension si vous n’avez besoin que de méthodes de filtre et de sélecteur spécifiques à un domaine.la source
Je pense que la seule raison de créer une classe spéciale pour la conservation d'une collection d'autres éléments doit être ajoutée lorsque vous ajoutez quelque chose de valeur, autre chose que simplement encapsuler / hériter d'une instance
IList
ou d'un autre type de collection.Par exemple, dans votre cas, ajouter une fonction qui renverrait des sous-listes de voitures garées sur des espaces de lots pairs / irréguliers ... fonction et est utilisé qu'une seule fois, quel est le point? KISS !
Maintenant, si vous envisagez d’offrir beaucoup de méthodes de tri / recherche, alors oui, je pense que cela pourrait être utile car c’est là qu’elles devraient appartenir, dans cette classe de collection spéciale. C'est également un bon moyen de "masquer" la complexité de certaines requêtes "trouver" ou de tout ce que vous pouvez faire avec une méthode de tri / recherche.
la source
Class
Je préfère utiliser l'option suivante pour pouvoir ajouter votre méthode à la collection et utiliser l'avantage de la liste.
et alors vous pouvez l'utiliser comme C # 7.0
Ou vous pouvez l'utiliser comme
- Version générique grâce au commentaire @Bryan
et alors vous pouvez l'utiliser
la source