简体   繁体   English

List.AddRange是否调用List.Add?

[英]Does List.AddRange call List.Add?

I have a custom class derived from List with an Add method that adds only if a certain condition is satisfied. 我有一个从List派生的自定义类,其中Add方法只在满足某个条件时才会添加。

Do I also need to override* AddRange, or does AddRange simply call Add on each element of the given range? 我是否还需要覆盖* AddRange,或者AddRange是否只是在给定范围的每个元素上调用Add?

*: Yes, new is hiding and not overriding in the context of C#. *:是的, new隐藏的,而不是在C#的上下文中覆盖。

If you want to create custom collection. 如果要创建自定义集合。 Don't derive it from List<T> but from Collection<T> or directly implement IList<T> or ICollection<T> . 不要从List<T>派生,而是从Collection<T>派生,或直接实现IList<T>ICollection<T> Indeed, the Add method in the List<T> class is not virtual. 实际上, List<T>类中的Add方法不是虚拟的。

Note: List<T>.AddRange uses Array.Copy . 注意: List<T>.AddRange使用Array.Copy

UPDATE UPDATE

When inheriting Collection you just have to override 2 methods! 继承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);
    }
}

If your items to validate are not string replace string in the code above by the correct type. 如果要验证的项目不是上面代码中的string替换string ,请使用正确的类型。

Don't use hiding that changes the semantics of the method. 不要使用隐藏方法来更改方法的语义。 That's really bad design. 这是非常糟糕的设计。

Create a new class that implements IList<T> . 创建一个实现IList<T>的新类。 The easiest way to do that is inheriting from Collection<T> . 最简单的方法是继承Collection<T> Collection<T> implements IList<T> and has four extension points in the form of protected virtual methods: Collection<T>实现了IList<T> ,并以protected virtual方法的形式有四个扩展点:

InsertItem
SetItem
RemoveItem
ClearItems

Since you only needs to validate items that get added and not those that get removed, you only need to override InsertItem and SetItem . 由于您只需要验证添加的项而不是需要删除的项,因此您只需要覆盖InsertItemSetItem

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

If you need a collection that behaves exactly like a List<T> , except for adding only valid objects, I wouldn't create a custom collection. 如果您需要一个行为与List<T>完全相同的集合,除了仅添加有效对象外,我不会创建自定义集合。

Use Extensions instead and call them AddIfValid(T value) and AddRangeIfValid(IEnumerable<T>) or whatever you like, as long as it's clear what the Extension is doing. 使用Extensions代替并调用它们AddIfValid(T value)AddRangeIfValid(IEnumerable<T>)或任何你喜欢的东西,只要它清楚扩展正在做什么。

Here's an example: 这是一个例子:

public static void AddIfValid(this List<T> list, T value)
{
    if (/* check if value is valid here */)
        list.Add(value);
}

Once you have defined your Extension, use it like this: 一旦定义了扩展,就像这样使用它:

myList.AddIfValid(myValue);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM