Допустим, у меня есть Car
класс:
public class Car
{
public string Engine { get; set; }
public string Seat { get; set; }
public string Tires { get; set; }
}
Допустим, мы создаем систему для парковки, я собираюсь использовать много Car
классов, поэтому мы создаем CarCollection
класс, который может иметь несколько дополнительных методов, таких как FindCarByModel
:
public class CarCollection
{
public List<Car> Cars { get; set; }
public Car FindCarByModel(string model)
{
// code here
return new Car();
}
}
Если я учусь на уроке ParkingLot
, что лучше?
Опция 1:
public class ParkingLot
{
public List<Car> Cars { get; set; }
//some other properties
}
Вариант № 2:
public class ParkingLot
{
public CarCollection Cars { get; set; }
//some other properties
}
Это даже хорошая практика для создания ClassCollection
другого Class
?
CarCollection
а неList<Car>
вокруг? Особенно учитывая, что CarCollection не расширяет класс Backing List и даже не реализует интерфейс Collection (я уверен, что в C # есть похожие вещи).public class CarCollection
не реализует IList или ICollection и т. Д. ... поэтому вы не можете передать его в список, который подходит для списка. Он заявляет как часть своего имени, что это коллекция, но не реализует ни один из этих методов.CarColection
сTotalTradeValue
собственностью на него. DDD - не единственный способ проектирования систем, просто указав его в качестве опции.Ответы:
До появления дженериков в .NET была обычная практика создания «типизированных» коллекций, чтобы вы могли иметь и
class CarCollection
т. Д. Для каждого типа, который нужно сгруппировать. В .NET 2.0 с введением Generics появился новый класс,List<T>
который избавляет вас от необходимости создавать иCarCollection
т. Д., Которые вы можете создатьList<Car>
.В большинстве случаев вы обнаружите, что этого
List<T>
достаточно для ваших целей, однако могут быть случаи, когда вы хотите иметь конкретное поведение в своей коллекции, если вы считаете, что это так, у вас есть несколько вариантов:List<T>
например,public class CarCollection { private List<Car> cars = new List<Car>(); public void Add(Car car) { this.cars.Add(car); }}
public class CarCollection : CollectionBase<Car> {}
Если вы используете подход инкапсуляции, вы должны как минимум выставить перечислитель, чтобы объявить его следующим образом:
Без этого вы не сможете перезаписать
foreach
коллекцию.Некоторые причины, по которым вы можете захотеть создать собственную коллекцию:
IList<T>
илиICollection<T>
Это хорошая практика? хорошо, это зависит от того, почему вы это делаете, если это, например, одна из причин, которые я перечислил выше, тогда да.
Microsoft делает это довольно регулярно, вот несколько сравнительно недавних примеров:
Что касается ваших
FindBy
методов, я хотел бы поместить их в методы расширения, чтобы их можно было использовать для любой коллекции, содержащей автомобили:Это отделяет задачу запроса коллекции от класса, в котором хранятся автомобили.
источник
ClassCollection
даже методы add, delete, update, добавив новый,CarCRUD
который будет инкапсулировать все эти методы ...CarCRUD
расширение, так как принудительно использовать его было бы сложно, преимущество использования пользовательской логики crud в классе коллекции состоит в том, что ее невозможно обойти. Кроме того, вы можете на самом деле не заботиться о логике поиска в базовой сборке, где иCar
т. Д. Объявляется, что может быть только пользовательским интерфейсом.Нет. Создание
XXXCollection
классов в значительной степени вышло из моды с появлением обобщений в .NET 2.0. На самом деле, есть замечательноеCast<T>()
расширение LINQ, которое люди используют в наши дни для извлечения материала из этих пользовательских форматов.источник
ClassCollection
? это хорошая практика, чтобы поставить их на главномClass
?FindCarByModel
методе, это имеет смысл как метод в вашем репозитории, который немного сложнее, чем простоCar
коллекция.Часто бывает удобно иметь доменно-ориентированные методы для поиска / нарезки коллекций, как в примере FindByCarModel выше, но нет необходимости прибегать к созданию классов коллекций-оболочек. В этой ситуации сейчас я обычно создаю набор методов расширения.
Вы добавляете так много фильтров или полезных методов к этому классу , как вам нравится, и вы можете использовать их везде, где есть
IEnumerable<Car>
, что включает в себя всеICollection<Car>
, массивыCar
, иIList<Car>
т.д.Поскольку у нашего решения для персистентности есть поставщик LINQ, я также часто создаю похожие методы фильтрации, которые работают и возвращают
IQueryable<T>
, поэтому мы можем применить эти операции и к хранилищу.Идиома .NET (ну, C #) сильно изменилась с 1.1. Поддержание пользовательских классов коллекций - это боль, и вы мало выигрываете от наследования,
CollectionBase<T>
поскольку вы не получаете решения с помощью метода расширений, если все, что вам нужно, - это специфичные для домена методы фильтрации и селектора.источник
Я думаю, что единственной причиной создания специального класса для хранения коллекции других элементов должно быть то, что вы добавляете в него что-то ценное, нечто большее, чем просто инкапсуляция / наследование от экземпляра
IList
или другого типа коллекции.Например, в вашем случае добавление функции, которая будет возвращать списки автомобилей, припаркованных на четных / неровных участках ... И даже тогда ... возможно, только если это часто используется повторно, потому что если он занимает только одну строку с хорошим LinQ функция и используется только один раз, какой смысл? ПОЦЕЛУЙ !
Теперь, если вы планируете предлагать много методов сортировки / поиска, тогда да, я думаю, что это может быть полезно, потому что это то, где они должны принадлежать, в этом специальном классе коллекции. Это также хороший способ «скрыть» сложности некоторых запросов «найти» или всего, что вы могли бы сделать в методе сортировки / поиска.
источник
Class
Я предпочитаю использовать следующую опцию, чтобы вы могли добавить свой метод в коллекцию и использовать преимущество списка.
и тогда вы можете использовать его как C # 7.0
Или вы можете использовать его как
- Общая версия благодаря комментарию @Bryan
и тогда вы можете использовать его
источник