C# 是否执行List.AddRange调用List.Add?
我有一个从List派生的自定义类,该类带有一个Add方法,该方法仅在满足某个条件时添加 我是否还需要重写*AddRange,或者AddRange只是在给定范围的每个元素上调用AddC# 是否执行List.AddRange调用List.Add?,c#,.net,list,C#,.net,List,我有一个从List派生的自定义类,该类带有一个Add方法,该方法仅在满足某个条件时添加 我是否还需要重写*AddRange,或者AddRange只是在给定范围的每个元素上调用Add *:是,new在C#的上下文中隐藏而不是重写。如果要创建自定义集合。不要从List派生它,而是从IList或ICollection派生或直接实现它。实际上,列表类中的Add方法不是虚拟的 注意:List.AddRange使用Array.Copy 更新 继承集合时,只需重写2个方法 public class MyCol
*:是,
new
在C#的上下文中隐藏而不是重写。如果要创建自定义集合。不要从List
派生它,而是从IList
或ICollection
派生或直接实现它。实际上,列表
类中的Add
方法不是虚拟的
注意:List.AddRange
使用Array.Copy
更新
继承集合时,只需重写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);
}
}
公共类MyCollection:集合
{
私有布尔IsValidItem(字符串项)
{
return;//您的条件:如果有效,则为true;否则为false。
}
//调用MyCollection.Add或MyCollection.Insert时将调用此方法
受保护的重写void插入项(int索引,字符串项)
{
if(IsValidItem(项目))
基本插入项(索引,项目);
}
//调用MyCollection[index]=newItem时将调用此方法
受保护的覆盖void SetItem(整数索引,字符串项)
{
if(IsValidItem(项目))
base.SetItem(索引,项);
}
}
如果要验证的项目不是
string
请将上述代码中的string
替换为正确的类型。如果您需要一个行为与列表
完全相同的集合,除了只添加有效对象之外,我不会创建自定义集合
改为使用扩展名,并将它们称为AddIfValid(T值)
和AddRangeIfValid(IEnumerable)
或任何您喜欢的,只要清楚扩展名在做什么
下面是一个例子:
public static void AddIfValid(this List<T> list, T value)
{
if (/* check if value is valid here */)
list.Add(value);
}
不要使用改变方法语义的隐藏。这真是糟糕的设计 创建一个实现IList的新类。最简单的方法是从
集合继承Collection
实现了IList
,并以受保护的虚拟
方法的形式具有四个扩展点:
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);
}
}
class MyCollection:集合
{
私有无效验证项(T项)
{
如果(项目无效)
抛出新ArgumentException(“项无效”);
}
受保护的重写插入项(int索引,T项)
{
验证项(项目);
基本插入项(索引,项目);
}
受保护的覆盖SetItem(int索引,T项)
{
验证项(项目);
base.SetItem(索引,项);
}
}
列表上的.Add
方法不是虚拟的,所以我想知道你是如何覆盖它的。@DarinDimitrov使用new
@Superbest“它实际上可以工作”算是一种好处吗?AddRange
调用Add
与否无关。它当然不会调用隐藏的Add
,而是调用隐藏的Add
。不,它不起作用。这是一个巨大的LSP违规。如何从集合
派生出“更多的工作”?@Superbest派生自集合
是实现IList
的一个特例,旨在简化您的特定问题。为什么它与List.AddRange()相关
实际实现?@svick List不能派生,因为它的方法不是虚拟的,与集合相反。List.AddRange是使用Array.Copy.Yes实现的,我理解。这就是为什么我问你为什么提到List.AddRange()
。它不会以这种或那种方式影响结果(正是因为List.Add()
不是虚拟的)。Collection
才是正确的选择。它就是为这种情况而设计的。@Superbest您不能重写Add,因为Add不是虚拟的,您只能隐藏它。“这真是糟糕的设计。”-为什么?@Superbest,因为对基类进行强制转换可以避免隐藏。违反LSP,您不再有一致的实现(IList.Add
,List.Add
,MyList.Add
不一致)等等。圆椭圆这样的东西不违反LSP吗?@Superbest:是的。还有很多其他的事情。你的观点是什么?
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);
}
}