【问题标题】:C#: Inheritance Problem with List<T>C#:List<T> 的继承问题
【发布时间】:2010-10-28 05:49:43
【问题描述】:

让我们假设这个类在 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 关键字。

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

谢谢 4 你的帮助

【问题讨论】:

  • 如果您要使用继承,也不要忘记覆盖接口其余部分的行为。否则你只需要创建一个有一个集合的集合,而不是一个集合。

标签: c# .net inheritance list


【解决方案1】:

否 - 不要在这里使用new;这不会给你多态性。 List&lt;T&gt; 不适合以这种方式继承;使用Collection&lt;T&gt;override 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--;
        }
    }
}

【讨论】:

  • 这是关于如何正确编码的更好的解释。谢谢马克
  • 比我必须实现整个界面吗?!
  • @Bigbohne,是的。您必须将所有呼叫转发到您的班级
  • @JaredPar - 如果你从 Collection 继承(它会为你完成所有转发到基础 IList
  • @Marc,我认为即使从 Collection 继承也是错误的,因为它违反了隐含的约束。我希望我通过 Add 添加到 Collection 的任何内容都可用,直到我 1)失去对对象的控制或 2)明确删除它。 LimitedCollection 将违反本合同
【解决方案2】:

您可以通过在声明中添加“new”来避免此警告。

public new void Add(T value) { 
 ...
}

但是,我认为您可能通过使用继承来解决这个问题有点错误。从我的角度来看,LimitedList 不是一个列表,因为它表达了非常不同的行为,因为它对列表中的数据量施加了严格的限制。我认为不从 List 继承而是将 List 作为成员变量会更好。

这是一个坏主意的另一个原因是,当您将课程视为列表时,您将无法满足课程的合同。以下代码将使用 List 的 Add 方法,而不是 LimitedList。

List<int> list = new LimitedList<int>(10);
for ( i = 0; i < 10000; i++ ) {
  list.Add(i);
}

【讨论】:

  • @Marc 完全同意这是错误的。我添加了一个例子,说明这是什么地方坏了。
  • @Dan 同意,这就是继承在这里不好的原因。
  • +1,同意封装一个 List 实例比从它继承要好得多。
【解决方案3】:

您需要将您的“添加”方法声明为“新”(替换)方法。 试试这个:

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 接口。 希望对您有所帮助。

【讨论】:

  • 查看其他关于多态性的回复,了解为什么这不是一个好主意。
【解决方案4】:

正如其他人所说,您需要添加新关键字。这是因为在基类 (List) 中,Add 方法没有用关键字“virtual”标记,这基本上意味着“可覆盖”。因此,应将其标记为“新”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-22
    • 1970-01-01
    • 1970-01-01
    • 2011-07-19
    • 2011-02-19
    • 2011-07-09
    • 1970-01-01
    • 2013-08-03
    相关资源
    最近更新 更多