Why Not Inherit from List≪T≫

Why not inherit from ListT?

There are some good answers here. I would add to them the following points.

What is the correct C# way of representing a data structure, which, "logically" (that is to say, "to the human mind") is just a list of things with a few bells and whistles?

Ask any ten non-computer-programmer people who are familiar with the existence of football to fill in the blank:

A football team is a particular kind of _____

Did anyone say "list of football players with a few bells and whistles", or did they all say "sports team" or "club" or "organization"? Your notion that a football team is a particular kind of list of players is in your human mind and your human mind alone.

List<T> is a mechanism. Football team is a business object -- that is, an object that represents some concept that is in the business domain of the program. Don't mix those! A football team is a kind of team; it has a roster, a roster is a list of players. A roster is not a particular kind of list of players. A roster is a list of players. So make a property called Roster that is a List<Player>. And make it ReadOnlyList<Player> while you're at it, unless you believe that everyone who knows about a football team gets to delete players from the roster.

Is inheriting from List<T> always unacceptable?

Unacceptable to whom? Me? No.

When is it acceptable?

When you're building a mechanism that extends the List<T> mechanism.

What must a programmer consider, when deciding whether to inherit from List<T> or not?

Am I building a mechanism or a business object?

But that's a lot of code! What do I get for all that work?

You spent more time typing up your question that it would have taken you to write forwarding methods for the relevant members of List<T> fifty times over. You're clearly not afraid of verbosity, and we are talking about a very small amount of code here; this is a few minutes work.

UPDATE

I gave it some more thought and there is another reason to not model a football team as a list of players. In fact it might be a bad idea to model a football team as having a list of players too. The problem with a team as/having a list of players is that what you've got is a snapshot of the team at a moment in time. I don't know what your business case is for this class, but if I had a class that represented a football team I would want to ask it questions like "how many Seahawks players missed games due to injury between 2003 and 2013?" or "What Denver player who previously played for another team had the largest year-over-year increase in yards ran?" or "Did the Piggers go all the way this year?"

That is, a football team seems to me to be well modeled as a collection of historical facts such as when a player was recruited, injured, retired, etc. Obviously the current player roster is an important fact that should probably be front-and-center, but there may be other interesting things you want to do with this object that require a more historical perspective.

Inheriting from ListT

If you want to create a publicly exposed animal collection you should not inherit from List<T> and instead inherit from Collection<T> and use the postfix Collection in the class name. Example: AnimalCollection : Collection<Animal>.

This is supported by the framework design guidelines, more specifically:

DO NOT use ArrayList, List<T>,
Hashtable, or Dictionary<K,V> in
public APIs. Use Collection<T>,
ReadOnlyCollection<T>,
KeyedCollection<K,T>, or
CollectionBase subtypes instead. Note
that the generic collections are only
supported in the Framework version 2.0
and above.

Inheriting ListT to implement collections a bad idea?

I wouldn't inherit from List<T> - it introduces issues like these, and doesn't really help (since there are no virtual methods to override). I would either use List<T> (or the more abstract IList<T>), or to introduce polymorphism Collection<T> has virtual methods.

As a note; re things like FindAll, you may also find the LINQ options (like .Where()) useful counterparts; most notably, they will work for any IList<T> (or IEnumerable<T>), not just List<T> and subclasses.

Clarification on why IListT doesn't inherit from IList

then one could cast to IList and add items not of the correct type.

This is only a partial justification: It is well possible to implement IList in a way so no items of an incorrect type can be added - as evidenced by the implementation that is List<T>.

However,, List<T> already exists as a part of the base class library. For our convenience, it implements IList and throws exceptions. If we want to use its IList implementation, we can do so within these constraints, and if we do not want to use it, we have no further work.

In contrast to this, IList<T> is an interface. If it inherited from IList, every implementor of IList<T> would have to implement all of the weakly-typed methods of IList, adding a lot of work that is often not desired.

Moreover, note that List<T> implements IList expilcitly. That means, the public interface of List<T> does not grow; you only get the IList methods if you explicitly cast to IList. In an interface, that is not possible, as an interface cannot enforce explicit implementation of another interface.

List property able to have different types that all inherit from the same class

I'm not sure I understand correctly what you want to accomplish, but it seems to me you want to make the FeatureCollection generic:

public class FeatureCollection<TFeature> where TFeature : Feature
{
public string Type { get; set; }
public List<TFeature> Features { get; set; }
}

Now FeatureCollection<FirstClass> can only store instances of FirstClass or instances of types that derive from FirstClass, while FeatureCollection<SecondClass> can't store FirstClass, but can store SecondClass...



Related Topics



Leave a reply



Submit