List.AddRange是否调用List.Add
本文关键字:List Add 调用 是否 AddRange | 更新日期: 2023-09-27 17:57:38
我有一个从List派生的自定义类,该类带有一个Add方法,只有在满足特定条件时才会添加。
我是否还需要覆盖*AddRange,或者AddRange只是在给定范围的每个元素上调用Add?
*:是的,new
隐藏,并且在C#上下文中不重写。
如果您想创建自定义集合。不要从List<T>
派生,而是从Collection<T>
派生,或者直接实现IList<T>
或ICollection<T>
。实际上,List<T>
类中的Add
方法不是虚拟的。
注: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);
}
}
如果您需要一个行为与List<T>
完全相似的集合,除了只添加有效对象之外,我不会创建自定义集合。
请使用Extensions,并将其称为AddIfValid(T value)
和AddRangeIfValid(IEnumerable<T>)
或任何您喜欢的名称,只要清楚Extension的作用即可。
这里有一个例子:
public static void AddIfValid(this List<T> list, T value)
{
if (/* check if value is valid here */)
list.Add(value);
}
一旦你定义了你的扩展,就这样使用它:
myList.AddIfValid(myValue);