49

What is the fastest way to implement a new class that inherits from List<T>?

class Animal {}

class Animals : List<Animal> {} // (1)

One problem I've encountered: By simply doing (1), I've found that I'm not getting the benefit of inheriting any constructors from List<T>.

In the end, I'd like Animals to behave a lot like a List<T> (e.g., can be constructed, compatibility with Linq). But in addition, I'd also like to be able to add my own custom methods.

DavidRR
  • 18,291
  • 25
  • 109
  • 191
pistacchio
  • 56,889
  • 107
  • 278
  • 420
  • 1
    What you've posted looks pretty good to me! – Stuart Mar 21 '11 at 10:16
  • Your code above would do it. You would need to implement any constructors and just call through to the relevant constructor on the base call (List). You can create any custom methods within the Animals class – detaylor Mar 21 '11 at 10:16
  • 1
    possible duplicate of [C#: Inheritance Problem with List](http://stackoverflow.com/questions/898152/c-inheritance-problem-with-listt) – George Stocker Mar 21 '11 at 12:29

6 Answers6

52

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.

Kols
  • 3,641
  • 2
  • 34
  • 42
João Angelo
  • 56,552
  • 12
  • 145
  • 147
  • 90
    I fail to understand why I should follow this guideline. – R. Martinho Fernandes Mar 21 '11 at 10:32
  • 1
    +1 this would really make sense if the OP wants to do something within the list itself.The OP could override basic methods. I don't really see any other value in inherit from a `List` just to call your list type `Animal` right? – gideon Mar 21 '11 at 10:35
  • 8
    @Martinho Fernandes, it's a *guideline* like any other, but if you provide a typed collection in your public API you can change it in future versions since it's your type. If you directly use List, then you're out of luck. – João Angelo Mar 21 '11 at 10:37
  • 8
    also consider using interfaces i.e. ICollection, IEnumerable, IDictionary etc. – chillitom Mar 21 '11 at 10:40
  • 8
    @Martinho: maybe 'cause you can't override Add/Remove methods while with `Collection` you can. BTW, I'd prefer to implement `IList`or `ICollection` using an inner `List` instead of inherit from `Collection`... – digEmAll Mar 21 '11 at 10:40
  • 1
    @digEmAll: What **you** want to override has no bearing on the public API. If I don't want to override anything, the fact that Add/Remove aren't virtual isn't a problem. What matters is what you want to make overridable by clients. @João: ok, that makes sense. I prefer using the interfaces with an inner List, as that gives you even more flexibility. – R. Martinho Fernandes Mar 21 '11 at 10:54
  • 1
    @Martinho: yes, you're right.. public API is not for implementers but for users :) – digEmAll Mar 21 '11 at 11:03
  • 1
    what `public APIs` actually stands for..?? is this like FB API or Google API for developers..?? – shashwat Feb 01 '13 at 14:54
  • 1
    I wanted access to the IEnumerable extension methods, so deriving from List was the best case for me – Tom Beech Sep 27 '13 at 16:32
  • 1
    @TomBeech, `Collection` implements `IEnumerable` and `IEnumerable`. What did you get with `List` that you would not get with `Collection`? – João Angelo Sep 27 '13 at 18:04
  • 1
    @JoãoAngelo I don't know about him, but I ended up at this question because I needed `List.AddRange` (see http://stackoverflow.com/questions/1474863/addrange-to-a-collection). How come only the class that you're not supposed to inherit from has this utility method? Wouldn't it be possible to add several elements to any collection? I feel like I'm missing some nuance about which logical construct `Collection` and `List` are supposed to correspond to. – Superbest Feb 11 '14 at 01:53
  • 1
    @Superbest, you should not inherit because it was not designed for extension but you can have your custom collection use composition with a inner list and then expose an `AddRange` method. As to the reasoning behind the disparity between lists and collections I can't help you there. – João Angelo Feb 11 '14 at 09:12
  • Why???????????? – Kröw May 24 '22 at 02:58
32

Constructors are not inherited along with the class. You have to reimplement your desired constructors.

public class AnimalsCollection : List<Animal>
{
     public AnimalsCollection(IEnumerable<Animal> animals) : base(animals) {} 
}
Anderson Imes
  • 25,500
  • 4
  • 67
  • 82
  • 13
    Downvoters want to say why? He asked why he "didn't have any constructors", which is why my answer is the way it is. If you disagree, how about leaving some feedback? – Anderson Imes Mar 21 '11 at 11:05
  • 5
    Same reason as for Tokk. But this shows once again why anonymous downvotes suck: It’s just not helping. – Konrad Rudolph Mar 21 '11 at 11:56
  • @Konrad Rudolph: what wasn't the OP's question. – Anderson Imes Mar 21 '11 at 12:25
  • 1
    see: stackoverflow.com/questions/3748931/ stackoverflow.com/questions/898152/ stackoverflow.com/questions/794679/ stackoverflow.com/questions/5207459/ stackoverflow.com/questions/2136213/ stackoverflow.com/questions/349904 stackoverflow.com/questions/1257214 – George Stocker Mar 21 '11 at 12:28
  • 2
    @George Stocker: That still wasn't the OP's question. It's good to give him a nudge in a better direction, but I sort of hate that we have to analyze every person's approach before answering the actual question the person had. Knowing that constructors are not inherited is a useful thing on its own. – Anderson Imes Mar 21 '11 at 12:34
  • @Anderson The correct answer is "Don't do that, do this instead." When someone is holding a gun wrongly, you don't gently tell them, "You shouldn't point that at your foot.", you take their hand and move the gun away from where ever they are pointing it. After that's done, then you can debate the virtue of whether you should let them point a gun at their own head. – George Stocker Mar 21 '11 at 12:40
  • 2
    @Anderson Yes but the general sentiment here isn’t to give the OPs a fish but to teach them fishing. *That said*, I wouldn’t have downvoted this answer and I I can only say again that anonymous downvotes suck. – Konrad Rudolph Mar 21 '11 at 12:40
  • Honestly I'm facing this problem myself and all the arguments I see against doing it this way are YAGNI. I really want a list class, but want to decorate it with a few extensions that don't break the encapsulation of the list. I'm unlikely to ever want to implement or inherit any other interfaces. I might be wrong about that in the very, very long run, but in that case I haven't painted myself into a corner doing this and I can refactor after I really hit those problems. – lamont Nov 30 '16 at 02:07
14

Deriving from List<T> is not advised. Primarily because List was never meant for extension, but for performance.

If you want to create your own specific collection, you should inherit from Collection<T>. In your case it would be:

class Animals : Collection<Animal> {}
Euphoric
  • 12,645
  • 1
  • 30
  • 44
  • 2
    I did according to ur advice and inherits from `Collection`. But having problem somewhere like `Collection` does not support methods like `Sort`, `Find`, `FindAll` and many more very useful methods. I have to change it to inherit from `List`. Is there any thing that I can do..? – shashwat Feb 01 '13 at 14:58
  • 4
    @shashwat It doesn't have those methods because a `Collection` is supposed to be a general class for representing any group of items. For instance, a mathematical set has no specific order, and cannot be sorted. `Find` may be ambiguous if elements are not unique. Both of these cases should be part of what `Collection` can be used for, so it cannot include `Sort` and `Find` without losing generality. Although there should probably be a `ListCollection : Collection`, since it seems that that's what people use it for most commonly. – Superbest Feb 11 '14 at 02:00
6

Bear in mind that inheriting from List isn't as fully featured as you may need, a lot of the members are not virtual so the only way of covering the base implementation is to shadow it with the new syntax (as opposed to override).

If you need to start exposing custom behaviour on standard list actions, I would implement all the list interfaces on a type that simply uses an inner list for the actual storage.

This is heavily dependent on your final requirements.

Adam Houldsworth
  • 63,413
  • 11
  • 150
  • 187
  • I did according to ur advice and inherits from `Collection`. But having problem somewhere like `Collection` does not support methods like `Sort`, `Find`, `FindAll` and many more very useful methods. I have to change it to inherit from `List`. Is there any thing that I can do..? – shashwat Feb 01 '13 at 15:01
  • 3
    @shashwat `Sort`, `Find` and `FindAll` etc can be implemented in terms of LINQ for `IEnumerable`, so this is not a problem. – Earth Engine Feb 12 '14 at 05:38
4
class Animals : List<Animal> {}

seemes the best way, because you can use it just after defining it like this.

So my advice is your questions title: Inherit List<T> ;-)

Tokk
  • 4,499
  • 2
  • 31
  • 47
  • 5
    Didn’t donwnvote but as a general rule you should *never* inherit from the concrete collection classes (and in fact they *should* have been made `sealed`). It is much preferred to either implement an interface or inherit from an abstract base class (such as `Collection`). – Konrad Rudolph Mar 21 '11 at 11:55
  • 1
    Agreed with Konrad. Inheriting from `List` is one of those things you should not do. Been discussed hundreds of times on Stack Overflow. – George Stocker Mar 21 '11 at 12:23
  • see: http://stackoverflow.com/questions/3748931/inheriting-listt-to-implement-collections-a-bad-idea http://stackoverflow.com/questions/898152/c-inheritance-problem-with-listt http://stackoverflow.com/questions/794679/question-inheriting-from-listof-t-class http://stackoverflow.com/questions/5207459/inheriting-from-listt-in-net-vb-or-c http://stackoverflow.com/questions/2136213/c-inherit-from-dictionary-iterate-over-keyvaluepairs/2136235#2136235 http://stackoverflow.com/questions/349904/ http://stackoverflow.com/questions/1257214/ – George Stocker Mar 21 '11 at 12:28
4

It isn't necessary to inherit from List to use collection initialization syntax or use Linq extension methods.

Just implement IEnumerable and also an Add method.

Daniel Earwicker
  • 114,894
  • 38
  • 205
  • 284