tags:

views:

86

answers:

5

If you frequently use in your program a collection which path would you prefer:

  1. Type List<T> everywhere.

  2. Define class:

    class TT:List<T>
    {
    }
    
  3. Define class:

    class TT
    {
       private List<T> _tt;
       // ...
    }
    

I think it's not very important, but after last project I started to think about it very often.

+3  A: 

You should only create your own collection class if it will add additional functionality.

When you do create your own collection classes, you should inherit from the System.Collections.ObjectModel.Collection<T> class, not List<T>.
Inheriting this class allows you to override InsertItem and RemoveItem and run custom logic when the collection is modified. (This is not possible when inheriting List<T>)

SLaks
public class TT:List<T> { public new void Add(T t) { base.Add(t)} } ???
JohnKZ
+1 for illuminating the `System.Collections.ObjectModel.Collection<T>` class
Brad
@JohnKZ: What about `AddRange`, `Insert`, `InsertRange`, and other methods? What if the object is casted back to `List<T>`?
SLaks
A: 

If I just need a list, I use 1. If I want to add additional methods and limitations, I will define 2.

Brad
A: 

Don't subclass List<> -- that's almost invariably a symptom of incorrect abstraction. Let a List be a list, nothing more. I don't have any idea why you'd want to use your 3rd option.

Kirk Woll
So Kirk, since you would *never* use #2, how do **you** define collections? `IEnumerable` and then code everything from scratch?
Brad
Wait, he isn't subclassing List<>, he's encapsulating it.
Bruno Brant
@Bruno, option 2 was inheriting from List<>, option 3 was encapsulating. Both were discussed.
Steve Haigh
@Brad, huh? My point was that it is rare that I *need* to define new collections. My suggestion was to use `List<>`. Not following you at all...
Kirk Woll
@Kirk, I didn't understand that you were suggesting to implement option 1. did you see @SLaks' suggestion to inherit the `System.Collections.ObjectModel.Collection<T>` class instead of `System.Collections.Generic.List<T>`? Would that resolve the issue of "incorrect abstraction"?
Brad
+2  A: 

You can use any option you specified depending on what you need:

(1) if you need to use list and type of the collection won't be changing.

(2) if you want to extend your collection with additional functionality then your should use inheritance.

(3) if you need to create additional level of the abstraction. In the this case your collection would be only implementation detail, e.g. you will be able to change list on the set in the future.

Andrew Bezzub
+1; good summary
Brad
A: 

Like everything, there are tradeoffs. The benefit of using a wrap class (encapsulating) your list is to militarize access to it. It means a lot of work:

  • You will have to add specific methods to add and remove from the list
  • You will have to add the iterator methods and might end up modifying syntax when iterating.

All these costs must serve a purpose. You'd do it if you want to intercept insertions and removals from the list, or if you want to create your own methods to filter the list and such. Maybe you need a immutable list. Make sure you have enough reasons to go through the trouble of creating the wrapper class.

Finally, as SLaks has put, it's better to inherit Collection<T> than to wrap around a list. I don't know the real differences, but I'd with this alternative.

Bruno Brant
Could you explain the term "militarize"? I've never come across it in this context before.
Steve Haigh
@Steve: I assume he means to secure it.
SLaks
@SLaks: Indeed. It was the wrong term.
Bruno Brant