C#:List<T>继承问题

6

假设这是C#中的一个类:

public class LimitedList<T> : List<T>
{
    private int _maxitems = 500;

    public void Add(T value) /* Adding a new Value to the buffer */
    {
        base.Add(value);
        TrimData(); /* Delete old data if lenght too long */
    }

    private void TrimData()
    {
        int num = Math.Max(0, base.Count - _maxitems);
        base.RemoveRange(0, num);
    }
}

编译器在 "public void Add(T value)" 这一行给了我这个警告:

警告 CS0108: 'System.LimitedList.Add(T)' 隐藏了继承的成员 'System.Collections.Generic.List.Add(T)'。如果是有意隐藏,请使用 new 关键字。

我该怎么做才能避免这个警告?

谢谢您的帮助。


1
不要忘记覆盖接口的其余行为,如果你要使用继承。否则,你只需要创建一个包含集合的集合,而不是一个集合。 - Dan Blair
4个回答

14

不要在这里使用 new,那样不能实现多态性。 List<T> 不是为了这种方式的继承而设计的;请使用 Collection<T> 并覆盖 Add InsertItem 方法。

public class LimitedCollection<T> : Collection<T>
{
    private int _maxitems = 500;

    protected override void InsertItem(int index, T item)
    {
        base.InsertItem(index, item);
        TrimData(); /* Delete old data if lenght too long */
    }

    private void TrimData()
    {
        int num = Math.Max(0, base.Count - _maxitems);
        while (num > 0)
        {
            base.RemoveAt(0);
            num--;
        }
    }
}

@JaredPar - 如果你从Collection<T>继承(它为您执行所有转发到基本IList<T>的操作),则不需要这样做。 - Marc Gravell
3
@Marc,我认为即使从Collection继承也是错误的,因为这违反了一个隐含的契约。我希望通过Add添加到Collection<T>中的任何内容都应该在以下情况下可用:1)失去对象的控制权或2)明确将其删除。LimitedCollection会违反这个契约。 - JaredPar
各位,我只想绘制实时数据。一个"普通"列表就可以,但是要无限增长。如果你们知道更好的方法,请告诉我。 - Bigbohne
说实话,我会创建一个名为LimitedList<of T>的新泛型类,并创建一个相关接口来完成我的工作 :p - Dan
听起来你实际上需要一个环形缓冲区来存储你的数字。http://en.wikipedia.org/wiki/Circular_buffer - dss539
显示剩余6条评论

11
您可以通过在声明中添加“new”来避免此警告。
public new void Add(T value) { 
 ...
}

然而,我认为您使用继承来解决这个问题可能有些不妥。在我的看法中,LimitedList不是一个List,因为它表现出非常不同的行为,它对List中的数据量施加了严格的限制。我认为最好不要从List继承,而是将List作为成员变量。
另一个原因是这是一个坏主意,因为当它被视为List时,您将无法满足类的合同。下面的代码将使用List的Add方法而不是LimitedList。
List<int> list = new LimitedList<int>(10);
for ( i = 0; i < 10000; i++ ) {
  list.Add(i);
}

@Marc 完全同意这是错误的。我添加了一个示例,说明它出了问题。 - JaredPar
@Dan同意,这就是为什么在这里继承不好的原因。 - JaredPar
+1,同意封装一个List<T>实例比继承它要好得多。 - Brian Ensink

0

你需要将你的“Add”方法声明为一个“new”(替换)方法。 试试这个:

public class LimitedList<T> : List<T>
{
    private int _maxitems = 500;

    public new void Add(T value) /* Adding a new Value to the buffer */
    {
        base.Add(value);
        TrimData(); /* Delete old data if length too long */
    }

    private void TrimData()
    {
        int num = Math.Max(0, base.Count - _maxitems);
        base.RemoveRange(0, num);
    }
}

注意在“Add(...”声明中使用了“new”关键字。

虽然在这种情况下,您应该创建自己的实现IList接口的通用类。 希望这有所帮助。


1
请查看其他关于多态性的回复,了解为什么这不是一个好主意。 - Marc Gravell

-1
像其他人所说的一样,你需要添加新关键字。这是因为在基类(List<T>)中,Add方法没有用关键字“virtual”标记,这意味着它不可重写。因此,它应该被标记为“new”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接