Is it a good practice to create a ClassCollection of another Class?

Lets says I have a Carclass:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public class Car
{
public string Engine { get; set; }
public string Seat { get; set; }
public string Tires { get; set; }
}
</code>
<code>public class Car { public string Engine { get; set; } public string Seat { get; set; } public string Tires { get; set; } } </code>
public class Car
{
    public string Engine { get; set; }
    public string Seat { get; set; }
    public string Tires { get; set; }
}

Lets say we’re making a system about a parking lot, I’m going to use a lot of the Car class, so we make a CarCollection class, it may has a few aditionals methods like FindCarByModel:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public class CarCollection
{
public List<Car> Cars { get; set; }
public Car FindCarByModel(string model)
{
// code here
return new Car();
}
}
</code>
<code>public class CarCollection { public List<Car> Cars { get; set; } public Car FindCarByModel(string model) { // code here return new Car(); } } </code>
public class CarCollection
{
    public List<Car> Cars { get; set; }

    public Car FindCarByModel(string model)
    {
        // code here
        return new Car();
    }
}

If I’m making a class ParkingLot, what’s the best practice?

Option #1:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public class ParkingLot
{
public List<Car> Cars { get; set; }
//some other properties
}
</code>
<code>public class ParkingLot { public List<Car> Cars { get; set; } //some other properties } </code>
public class ParkingLot
{
    public List<Car> Cars { get; set; }
    //some other properties
}

Option #2:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public class ParkingLot
{
public CarCollection Cars { get; set; }
//some other properties
}
</code>
<code>public class ParkingLot { public CarCollection Cars { get; set; } //some other properties } </code>
public class ParkingLot
{
    public CarCollection Cars { get; set; }
    //some other properties
}

Is it even a good practice to create a ClassCollection of another Class?

5

Prior to generics in .NET, it was common practice to create ‘typed’ collections so you would have class CarCollection etc for every type you needed to group. In .NET 2.0 with the introduction of Generics, a new class List<T> was introduced which saves you having to create CarCollection etc as you can create List<Car>.

Most of the time, you will find that List<T> is sufficient for your purposes, however there may be times that you want to have specific behaviour in your collection, if you believe this to be the case, you have a couple of options:

  • Create a class which encapsulates List<T> for example public class CarCollection { private List<Car> cars = new List<Car>(); public void Add(Car car) { this.cars.Add(car); }}
  • Create a custom collection public class CarCollection : CollectionBase<Car> {}

If you go for the encapsulation approach, you should at minimum expose the enumerator so you would declare it as follows:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public class CarCollection : IEnumerable<Car>
{
private List<Car> cars = new List<Car>();
public IEnumerator<Car> GetEnumerator() { return this.cars.GetEnumerator(); }
}
</code>
<code>public class CarCollection : IEnumerable<Car> { private List<Car> cars = new List<Car>(); public IEnumerator<Car> GetEnumerator() { return this.cars.GetEnumerator(); } } </code>
public class CarCollection : IEnumerable<Car>
{
    private List<Car> cars = new List<Car>();

    public IEnumerator<Car> GetEnumerator() { return this.cars.GetEnumerator(); }
}

Without doing that, you can’t do a foreach over the collection.

Some reasons you might want to create a custom collection are:

  • You don’t want to fully expose all the methods in IList<T> or ICollection<T>
  • You want to perform additional actions upon adding or removing an item from the collection

Is it good practice? well that depends on why you are doing it, if it is for example one of the reasons I have listed above then yes.

Microsoft do it quite regularly, here are some fairly recent examples:

  • System.Web.Http.Filters.HttpFilterCollection
  • System.Web.Mvc.ModelBinderProviderCollection

As for your FindBy methods, I would be tempted to put them in extension methods so that they can be used against any collection containing cars:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public static class CarLookupQueries
{
public static Car FindByLicencePlate(this IEnumerable<Car> source, string licencePlate)
{
return source.SingleOrDefault(c => c.LicencePlate == licencePlate);
}
...
}
</code>
<code>public static class CarLookupQueries { public static Car FindByLicencePlate(this IEnumerable<Car> source, string licencePlate) { return source.SingleOrDefault(c => c.LicencePlate == licencePlate); } ... } </code>
public static class CarLookupQueries
{
    public static Car FindByLicencePlate(this IEnumerable<Car> source, string licencePlate)
    {
        return source.SingleOrDefault(c => c.LicencePlate == licencePlate);
    }

    ...
}

This separates the concern of querying the collection from the class which stores the cars.

3

No. The creation of XXXCollection classes pretty much fell out of style with the advent of generics in .NET 2.0. In fact, there is the nifty Cast<T>() LINQ extension that folks use these days to get stuff out of those custom formats.

2

It’s often handy to have domain-oriented methods to find / slice collections, as in the FindByCarModel example above, but there’s no need to resort to creating wrapper collection classes. In this situation I will now typically create a set of extension methods.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public static class CarExtensions
{
public static IEnumerable<Car> ByModel(this IEnumerable<Car> cars, string model)
{
return cars.Where(car => car.Model == model);
}
}
</code>
<code>public static class CarExtensions { public static IEnumerable<Car> ByModel(this IEnumerable<Car> cars, string model) { return cars.Where(car => car.Model == model); } } </code>
public static class CarExtensions
{
    public static IEnumerable<Car> ByModel(this IEnumerable<Car> cars, string model)
    {
        return cars.Where(car => car.Model == model);
    }
}

You add as many filter or utility methods to that class as you like, and you can use them anywhere you have IEnumerable<Car>, which includes anything ICollection<Car>, arrays of Car, IList<Car> etc.

Since our persistence solution has a LINQ provider, I’ll frequently also create similar filter methods that operate on and return IQueryable<T>, so we can apply these operations to the repository too.

The idiom of .NET (well, C#) has changed a lot since 1.1. Maintaining custom collection classes is a pain, and you gain little from inheriting from CollectionBase<T> that you don’t get with the extension method solution if all you need is domain-specific filter and selector methods.

I think that the only reason to create a special class for holding a collection of other items should be when you add something of value to it, something more than just encapsulate/inherit from an instance of IList or another type of collection.

For example, in your case, adding a function that would return sublists of cars parked on even/uneven lot spaces… And even then… maybe only if it’s often reused, because if it only takes one line with a nice LinQ function and is used only once, what’s the point ? KISS !

Now, if you plan to offer a lot of sorting/finding methods, then yes, I think this could be useful because this is where they should belong, in that special collection class. This is also a good way for “hiding” the complexities of some “find” queries or whatever you could do in a sorting/finding method.

2

I prefer to go with the following option, so you can add you method to the collection and use the advantage of list.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public class CarCollection:List<Car>
{
public Car FindCarByModel(string model)
{
// code here
return new Car();
}
}
</code>
<code>public class CarCollection:List<Car> { public Car FindCarByModel(string model) { // code here return new Car(); } } </code>
public class CarCollection:List<Car>
{
    public Car FindCarByModel(string model)
    {
        // code here
        return new Car();
    }
}

and then you can use it like C#7.0

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public class ParkingLot
{
public CarCollection Cars { get; set; }=new CarCollection();
//some other properties
}
</code>
<code>public class ParkingLot { public CarCollection Cars { get; set; }=new CarCollection(); //some other properties } </code>
public class ParkingLot
{
    public CarCollection Cars { get; set; }=new CarCollection();
    //some other properties
}

Or you can use it like

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public class ParkingLot
{
public ParkingLot()
{
//initial set
Cars =new CarCollection();
}
public CarCollection Cars { get; set; }
//some other properties
}
</code>
<code>public class ParkingLot { public ParkingLot() { //initial set Cars =new CarCollection(); } public CarCollection Cars { get; set; } //some other properties } </code>
public class ParkingLot
{
   public ParkingLot()
   {
      //initial set
      Cars =new CarCollection();
   }
    public CarCollection Cars { get; set; }
    //some other properties
}

— Generic version thanks to @Bryan comment

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code> public class MyCollection<T>:List<T> where T:class,new()
{
public T FindOrNew(Predicate<T> predicate)
{
// code here
return Find(predicate)?? new T();
}
//Other Common methods
}
</code>
<code> public class MyCollection<T>:List<T> where T:class,new() { public T FindOrNew(Predicate<T> predicate) { // code here return Find(predicate)?? new T(); } //Other Common methods } </code>
   public class MyCollection<T>:List<T> where T:class,new()
    {
        public T FindOrNew(Predicate<T> predicate)
        {
            // code here
            return Find(predicate)?? new T();
        }
       //Other Common methods
     }

and then you can use it

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public class ParkingLot
{
public MyCollection<Car> Cars { get; set; }=new MyCollection<Car>();
public MyCollection<Motor> Motors{ get; set; }=new MyCollection<Motor>();
public MyCollection<Bike> Bikes{ get; set; }=new MyCollection<Bike>();
//some other properties
}
</code>
<code>public class ParkingLot { public MyCollection<Car> Cars { get; set; }=new MyCollection<Car>(); public MyCollection<Motor> Motors{ get; set; }=new MyCollection<Motor>(); public MyCollection<Bike> Bikes{ get; set; }=new MyCollection<Bike>(); //some other properties } </code>
public class ParkingLot
{
    public MyCollection<Car> Cars { get; set; }=new MyCollection<Car>();
    public MyCollection<Motor> Motors{ get; set; }=new MyCollection<Motor>();
    public MyCollection<Bike> Bikes{ get; set; }=new MyCollection<Bike>();
    //some other properties
}

4

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật