我有一个从 List 派生的自定义类,它带有一个 Add 方法,该方法仅在满足特定条件时才添加。
我是否还需要覆盖* AddRange,或者 AddRange 是否只是在给定范围的每个元素上调用 Add?
*:是的,在 C# 的上下文new
中隐藏而不是覆盖。
如果要创建自定义集合。不要List<T>
从Collection<T>
或直接实现IList<T>
or派生它ICollection<T>
。事实上,类中的Add
方法List<T>
不是虚拟的。
注意:List<T>.AddRange
使用Array.Copy
.
继承 Collection 时,您只需覆盖 2 个方法!
public class MyCollection : Collection<string>
{
private bool IsValidItem(string item)
{
return; // Your condition : true if valid; false, otherwise.
}
// This method will be called when you call MyCollection.Add or MyCollection.Insert
protected override void InsertItem(int index, string item)
{
if(IsValidItem(item))
base.InsertItem(index, item);
}
// This method will be called when you call MyCollection[index] = newItem
protected override void SetItem(int index, string item)
{
if(IsValidItem(item))
base.SetItem(index, item);
}
}
如果您要验证的项目没有在上面的代码中string
替换string
为正确的类型。
不要使用改变方法语义的隐藏。这真是糟糕的设计。
创建一个实现IList<T>
. 最简单的方法是继承自Collection<T>
. Collection<T>
以方法的形式实现IList<T>
并具有四个扩展点protected virtual
:
InsertItem
SetItem
RemoveItem
ClearItems
由于您只需要验证添加的项目而不是删除的项目,因此您只需覆盖InsertItem
和SetItem
.
class MyCollection:Collection<T>
{
private void ValidateItem(T item)
{
if(item is invalid)
throw new ArgumentException("Item is invalid");
}
protected override InsertItem(int index, T item)
{
ValidateItem(item);
base.InsertItem(index, item);
}
protected override SetItem(int index, T item)
{
ValidateItem(item);
base.SetItem(index, item);
}
}
如果您需要一个行为与 a 完全相同的集合List<T>
,除了仅添加有效对象之外,我不会创建自定义集合。
只要清楚扩展程序在做什么,请改用扩展程序并调用它们AddIfValid(T value)
或您喜欢的任何名称。AddRangeIfValid(IEnumerable<T>)
这是一个例子:
public static void AddIfValid(this List<T> list, T value)
{
if (/* check if value is valid here */)
list.Add(value);
}
一旦你定义了你的扩展,像这样使用它:
myList.AddIfValid(myValue);