8

Can't i overload List's Add method ?

class ListDemo<T>:List<T>
 {
    public override T  Add<T>(T value)
   {
      return base.Add(value);
   }
}

I am receiving the following error :

1) Type parameter 'T' has the same name as the type parameter from outer type 'CollectionsExample.ListDemo

2) 'CollectionsExample.ListDemo.Add(T)': no suitable method found to override

user196546
  • 2,513
  • 4
  • 23
  • 18
  • 6
    Why are you subclassing `List` instead of just implementing `IList` (and favoring composition instead of inheritance)? – Daniel Pryden Oct 26 '09 at 17:17
  • Also, exact duplicate: http://stackoverflow.com/questions/580202/how-to-i-override-listts-add-method-in-c – Daniel Pryden Oct 26 '09 at 17:22
  • @ Daniel Pryden .Thanks .I am beginner. learning from you people. – user196546 Oct 26 '09 at 17:38
  • 4
    @Daniel: How many times do you re-implement the `IList` interface in your projects? `System.Collections.ObjectModel.Generic.Collection` is almost always a better choice if all you want to do is override methods like `Add` or `Remove` of a list. – LBushkin Oct 26 '09 at 17:51

6 Answers6

20

Instead of subclassing from List<T>, you should encapsulate List<T> and implement IList<T>. This makes it easy to handle "overriding" the behavior of Add:

public class ListDemo<T> : IList<T>
{
    private List<T> list = new List<T>(); // Internal list
    public void Add(T item)
    {
       // Do your pre-add logic here
       list.Add(item); // add to the internal list
       // Do your post-add logic here
    }

    // Implement all IList<T> methods, just passing through to list, such as:
}

List<T> should not be part of your public API - it should be an implementation detail.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 8
    `Collection` is a customizable implementation backed by a `List`, so it should be seriously considered over re-rolling the code to keep it simple (and keep the focus on the parts where this implementation differs from `List`). – Sam Harwell Oct 26 '09 at 17:35
7

The correct code is:

class ListDemo<T>:List<T>
{
    public new void Add(T value)
    {
      base.Add(value);
    }
}

You don't need a type parameter on both the class declaration and the method. It is the class declaration that is generic in this case; so when you try to declare the Add method as taking a generic type parameter named T, the compiler will complain that you are trying to have 2 type parameters with the same name.

Edit: Fixed the code sample. Since Add is not virtual, it cannot be overridden with the override keyword (so the original sample would actually not compile). You can still declare it using new, but that could lead to different meaning of your Add method. I would strongly consider just implementing IList<T>, as suggested in the comments.

driis
  • 161,458
  • 45
  • 265
  • 341
  • 1
    You are correct, this code will compile. But because `List.Add()` isn't declared as virtual, if you use this `ListDemo` class in code that expects a `List`, the overridden `Add()` method won't get called. – Daniel Pryden Oct 26 '09 at 17:23
  • This will warn. You should use new, not override, but that's not going to do what you expect... – Reed Copsey Oct 26 '09 at 17:27
  • 2
    -1 - this is not correct. List.Add is not marked as virtual so your solution won't work. – Rob Levine Oct 26 '09 at 17:31
  • -1: Hiding `Add(T)` is a sure way to introduce nasty bugs in your application. The code will actually change behaviors based on whether it's held in a `List` or `ListDemo` variable, but will never warn you about which one is in use at any given time. This is a HUGE no-no. – Sam Harwell Oct 26 '09 at 17:44
  • @280Z28, I agree, but it is the correct answer to the question. I woudl also prefer another approach. – driis Oct 26 '09 at 17:47
4

This worked for me (based on Sam Harwell's comment):

public class ListDemo<T> : Collection<T>
{
    protected override void InsertItem(int index, T item)
    {
        // Your add condition ...
        if (!this.Any(x => ...))
            base.InsertItem(index, item);
    }
}
IngoB
  • 2,552
  • 1
  • 20
  • 35
3

If you want a collection in which you'd want to override your Add/Insert or Indexer then you could create your own collection that would inherit from:

Collection<T>

and override the following methods:

InsertItem();
SetItem();

the first one is called by Add() and Insert(), while the second is called by this[]

The List<T> Add can not be overriden since the collection is made for perfomance, thus the overriding possibility is intentionally removed

Askar Rayapov
  • 139
  • 1
  • 7
1

Deriving from List<T> is almost always pointless. See my answer to this other question for a full rundown:

How to create a custom collection in .NET 2.0

Community
  • 1
  • 1
Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
0

Deriving from List is not pointless if that is the class that gives you what you need. And all you want to do is add a couple methods, such as FindCar(Car dodge).

VMAtm
  • 27,943
  • 17
  • 79
  • 125