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
, orDictionary<K,V>
in
public APIs. UseCollection<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
How to Parse a Json String That Would Cause Illegal C# Identifiers
The Entity Cannot Be Constructed in a Linq to Entities Query
Pass List of Checkboxes into View and Pull Out Ienumerable
Passing Objects by Reference or Value in C#
Difference Between Property and Field in C# 3.0+
Processstartinfo Hanging on "Waitforexit" - Why
What Are Regular Expression Balancing Groups
Json.Net: How to Deserialize Without Using the Default Constructor
How to Read a CSV File into a .Net Datatable
Why Is Jsonrequestbehavior Needed
What Are Some Good .Net Profilers
An Async/Await Example That Causes a Deadlock
How to Get the Path of the Assembly the Code Is In
Elevating Process Privilege Programmatically
Best Way to Randomize an Array With .Net
Direct Casting VS 'As' Operator