【问题标题】:Custom (derived) List<T>自定义(派生)列表<T>
【发布时间】:2013-12-27 22:06:42
【问题描述】:

随意装上你的枪并瞄准,但我想了解你为什么不应该这样做。

我创建了一个自定义类,旨在替换 List 的任何实例(我用它来更新它们后面的 XML 对象):

public class ListwAddRemove<T> : List<T> {
    public event EventHandler<ListModifyEventArgs> OnAdd;
    public event EventHandler<ListModifyEventArgs> OnRemove;

    new public void Add(T o) {
        base.Add(o);

        if (OnAdd != null) {
            OnAdd(this, new ListModifyEventArgs(o));
        }
    }

    new public void Remove(T o) {
        base.Remove(o);

        if (OnRemove != null) {
            OnRemove(this, new ListModifyEventArgs(o));
        }
    }
}

这个想法是每当我从这个列表中添加或删除一个项目时,我的绑定事件都会触发,我可以自动处理后面的 XML。

这就像一个魅力,到目前为止一切顺利。

但是如何处理 object.ToList() 和我的派生版本之间的转换?

很多人说你应该从 Collection 派生而不是......为什么?

【问题讨论】:

  • 我使用的是 Windows Forms .Net 3.5
  • 使用new 修饰符对基类隐藏成员绝不是一个好主意。如果您真的想从List&lt;&gt; 派生,请给您的方法一些新名称,例如AddAndRaiseEvent 或类似名称。然而,List&lt;&gt; 类并不是真正为这种用途而设计的。还有其他类提供更多 virtual 成员,以便在继承它们时有所帮助。
  • @user1830285 ObservableCollection 在 .Net 3.5 中仍然可用,并且可以与 Windows 窗体一起使用,它只是一个实现 INotifyCollectionChangedINotifyPropertyChanged 接口的集合。请参阅stackoverflow.com/questions/4279185/… 了解更多信息。

标签: c# linq collections derived-class


【解决方案1】:

您应该从 Collection&lt;T&gt; 派生,因为它旨在允许您覆盖 InsertItemRemoveItem 以添加自定义行为,例如您正在做的事情(还有 SetItem,以在更改现有项目)。

因此它可以用作IList&lt;T&gt;,任何插入/删除都将自动使用自定义。

在您的情况下,转换为 IList&lt;T&gt; 或基类 List&lt;T&gt; 的任何人都将绕过您的自定义添加/删除功能。

Collection&lt;T&gt; 还提供了一个构造函数来包装现有列表。您可以从派生类中公开它以包装由Enumerable&lt;T&gt;.ToList() 生成的列表。

更新

请问公开构造函数的语法是什么?

很简单:

public class ListwAddRemove<T> : Collection<T>
{
    public ListwAddRemove<T>()
    {
    }

    public ListwAddRemove<T>(IList<T> list) : base(list)
    {
    }

    ... implementation of overrides for InsertItem, SetItem, RemoveItem ...
}

然后按如下方式使用:

IList<SomeType> list = ....ToList();
ListwAddRemove<SomeType> myList = new ListwAddRemove<SomeType>(list);

【讨论】:

  • 转换为IList&lt;T&gt; 接口的任何人都将失去新功能,但转换为基类List&lt;T&gt; 的任何人都将失去新功能(如MartinStettner 的回答)。
  • “你可以从你的派生类中公开它来包装一个由”生成的列表......请问公开构造函数的语法是什么?我喜欢这个实现
  • 没关系:public ListwAddRemove(List incomingList) : base(incomingList) { }
【解决方案2】:

一个,

void DoSomeAddingToList(List<int> list) {
  list.Add(1);
}

var list = new ListwAddRemove<int>();
DoSomeAddingToList(list);

不会触发事件。这可能会导致奇怪的效果,尤其是如果您不是唯一使用该类的人。

List&lt;T&gt;AddRemove 定义了一个非常具体的行为(因为它是一个具体的类),用户可能完全依赖于这个行为。

我认为使用new 修饰符通常是正确的,因此应谨慎使用此语言功能,尤其是在公共方法上。

正如其他人所提到的,实施 IList&lt;T&gt;(使用委托/聚合)可能是更好的选择。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-19
    • 2018-01-05
    • 1970-01-01
    • 2015-07-14
    • 2019-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多