关于c#:覆盖列表< T>的Add()

Overriding List<T>'s Add()

我不能重载列表的添加方法吗?

1
2
3
4
5
6
7
class ListDemo<T>:List<T>
 {
    public override T  Add<T>(T value)
   {
      return base.Add(value);
   }
}

我收到以下错误:

1)类型参数"t"与外部类型"CollectionsExample.ListDemo"中的类型参数同名

2)"collectionsExample.listmemo.add(t)":找不到要重写的合适方法


不是从List中进行子类化,而是封装List并实现IList。这使得处理"覆盖"添加的行为很容易:

1
2
3
4
5
6
7
8
9
10
11
12
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不应该是公共API的一部分—它应该是一个实现细节。


正确的代码是:

1
2
3
4
5
6
7
class ListDemo<T>:List<T>
{
    public new void Add(T value)
    {
      base.Add(value);
    }
}

类声明和方法都不需要类型参数。在这种情况下,类声明是泛型的;因此,当您尝试将add方法声明为使用名为t的泛型类型参数时,编译器会抱怨您试图使用两个同名的类型参数。

编辑:修复了代码示例。由于add不是虚拟的,因此不能用override关键字重写它(因此原始示例实际上不会编译)。您仍然可以使用new声明它,但这可能会导致add方法的不同含义。正如评论中所建议的,我会强烈考虑只实现IList。


如果要在其中重写添加/插入或索引器的集合,则可以创建自己的集合,该集合将从以下对象继承:

1
Collection<T>

并重写以下方法:

1
2
InsertItem();
SetItem();

第一个由add()和insert()调用,而第二个则由这个[]

由于集合是为了执行而创建的,因此不能重写Listadd,因此有意删除重写的可能性。


这对我很有效(基于山姆·哈威尔的评论):

1
2
3
4
5
6
7
8
9
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);
    }
}

List派生几乎总是毫无意义的。请参阅我对另一个问题的回答,了解完整的概要:

如何在.NET 2.0中创建自定义集合


从列表派生并不是毫无意义的,如果这是一个类,它提供了您需要的东西。你所要做的就是添加一些方法,比如FindCar(Car dodge).