【问题标题】:Overriding List<T>'s Add()覆盖 List<T> 的 Add()
【发布时间】:2009-10-26 17:15:34
【问题描述】:

不能重载 List 的 Add 方法吗?

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

我收到以下错误:

1) 类型参数“T”与外部类型“CollectionsExample.ListDemo”中的类型参数同名

2) 'CollectionsExample.ListDemo.Add(T)': 找不到合适的方法来覆盖

【问题讨论】:

  • 你为什么要继承 List&lt;T&gt; 而不是仅仅实现 IList&lt;T&gt; (并且支持组合而不是继承)?
  • 另外,完全相同:stackoverflow.com/questions/580202/…
  • @Daniel Pryden。谢谢。我是初学者。向你们学习。
  • @Daniel:您在项目中重新实现了多少次IList&lt;T&gt; 接口?如果您只想覆盖列表中的AddRemove 等方法,System.Collections.ObjectModel.Generic.Collection&lt;T&gt; 几乎总是更好的选择。

标签: c# collections


【解决方案1】:

这对我有用(基于 Sam Harwell 的评论):

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);
    }
}

【讨论】:

    【解决方案2】:

    您应该封装List&lt;T&gt; 并实现IList&lt;T&gt;,而不是从List&lt;T&gt; 继承。这使得处理“覆盖” 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&lt;T&gt; 不应该是您的公共 API 的一部分 - 它应该是一个实现细节。

    【讨论】:

    • Collection&lt;T&gt; 是一个由List&lt;T&gt; 支持的可定制实现,因此应该认真考虑重新滚动代码以使其保持简单(并将重点放在此实现不同的部分来自List&lt;T&gt;)。
    【解决方案3】:

    如果您想要一个要覆盖您的 Add/Insert 或 Indexer 的集合,那么您可以创建自己的集合来继承:

    Collection<T>
    

    并覆盖以下方法:

    InsertItem();
    SetItem();
    

    第一个由 Add() 和 Insert() 调用, 而第二个由 this[]

    调用

    List&lt;T&gt; Add 不能被覆盖,因为集合是为性能而设计的,因此有意删除了覆盖的可能性

    【讨论】:

    • 意思是我整个项目中使用Add()方法的方式不需要改变吧?
    【解决方案4】:

    正确的代码是:

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

    类声明和方法都不需要类型参数。在这种情况下,类声明是通用的;因此,当您尝试将 Add 方法声明为采用名为 T 的泛型类型参数时,编译器会抱怨您尝试使用 2 个具有相同名称的类型参数。

    编辑:修复了代码示例。由于 Add 不是虚拟的,因此不能用 override 关键字覆盖它(因此原始示例实际上不会编译)。您仍然可以使用 new 声明它,但这可能会导致您的 Add 方法具有不同的含义。按照 cmets 中的建议,我强烈考虑只实施 IList

    【讨论】:

    • 你是对的,这段代码会编译。但是因为List.Add() 没有被声明为虚拟的,如果你在需要List 的代码中使用这个ListDemo 类,被覆盖的Add() 方法将不会被调用。
    • 这会发出警告。您应该使用新的,而不是覆盖,但这不会达到您的预期......
    • -1 - 这是不正确的。 List.Add 未标记为虚拟,因此您的解决方案将不起作用。
    • -1:隐藏Add(T) 是在您的应用程序中引入讨厌的错误的可靠方法。代码实际上会根据它是否保存在List&lt;T&gt;ListDemo&lt;T&gt; 变量中而改变行为,但永远不会在任何给定时间警告您哪个正在使用。这是一个巨大的禁忌。
    • @280Z28,我同意,但这是问题的正确答案。我也更喜欢另一种方法。
    【解决方案5】:

    List&lt;T&gt; 派生几乎总是毫无意义的。请参阅我对其他问题的回答以获得完整的概要:

    How to create a custom collection in .NET 2.0

    【讨论】:

      【解决方案6】:

      从 List 派生并不是没有意义的,如果那是给你所需要的类。而你要做的就是添加几个方法,比如FindCar(Car dodge).

      【讨论】:

        猜你喜欢
        • 2010-10-09
        • 2012-11-21
        • 2021-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-16
        • 2019-08-01
        • 2015-04-30
        相关资源
        最近更新 更多