【问题标题】:c# .net Create a list from two object list - Performance differences [duplicate]c# .net 从两个对象列表创建列表 - 性能差异 [重复]
【发布时间】:2018-01-16 13:21:44
【问题描述】:

我想知道这两种从 2 个(或更多)对象列表创建列表的方法在性能上是否存在差异。

我问是因为作为初学者,我使用方式 2(在许多小型项目中)编写了大多数情况,所以我想知道是否应该用方法 1 替换方法 2。

示例来自:Create a list from two object lists with linq

方式一:

var mergedList=new List<Person>();
mergeList.AddRange(list1);
mergeList.AddRange(list2);

方式二:

var mergedList=new List<Person>();

foreach(var item in list1)
{
    mergedList.Add(item);
}
foreach(var item in list2)
{
     mergedList.Add(item);
}

【问题讨论】:

  • 有些东西是马,有些东西与它们赛跑。您是否尝试过任何性能监控?
  • 再一次向ericlippert.com/2012/12/17/performance-rant 提出问题,不要寻找没有问题的问题。或者换句话说:"premature optimization is the root of all evil"。话虽如此,你根本不应该用另一个替换所有出现的情况,除非你有强烈的需要这样做。
  • List 确实有一个以容量为参数的构造函数。它是内部数组中保留的插槽数量。列表以 10 的容量开始,如果您在上面添加项目,则必须重新创建内部数组并每次复制现有项目。在您的情况下,您知道要插入的列表的大小,因此您可以使用 list1.Count + list2.Count 的容量初始化合并列表。

标签: c# .net list linq


【解决方案1】:

好吧,您可能不会注意到差异,因此您使用循环的旧方法非常好。但是使用方式 1,您可以节省几行代码。 List.AddRange 确实可以更高效一点,因为当您传递一个集合类型(有一个 Count property)时,它可以用正确的大小初始化列表(以及底层存储是一个数组)。如果数组没有以正确的大小初始化,则必须在循环中调整大小。

可以在source(InsertRange调用自AddRange)中看到优化方法:

public void InsertRange(int index, IEnumerable<T> collection) {
    // ...

    ICollection<T> c = collection as ICollection<T>;
    if( c != null ) {    // if collection is ICollection<T>
     // this is the optimzed version if you use AddRange with a list
        int count = c.Count;
        if (count > 0) {
            EnsureCapacity(_size + count);
            if (index < _size) {
                Array.Copy(_items, index, _items, index + count, _size - index);
            }

            // If we're inserting a List into itself, we want to be able to deal with that.
            if (this == c) {
                // Copy first part of _items to insert location
                Array.Copy(_items, 0, _items, index, index);
                // Copy last part of _items back to inserted location
                Array.Copy(_items, index+count, _items, index*2, _size-index);
            }
            else {
                T[] itemsToInsert = new T[count];
                c.CopyTo(itemsToInsert, 0);
                itemsToInsert.CopyTo(_items, index);                    
            }
            _size += count;
        }                
    }
    else {
    // this is the loop version that you use
        using(IEnumerator<T> en = collection.GetEnumerator()) {
            while(en.MoveNext()) {
                Insert(index++, en.Current);                                    
            }                
        }
    }
    _version++;            
}

【讨论】:

  • 感谢您的好回答和无毒。
【解决方案2】:

将回答其他问题,作为高级语言的开发人员,您应该对代码的简单性感兴趣。如果您遇到性能问题 - 请尝试解决它!

您的代码执行相同的操作,您不会注意到任何性能差异 =)

【讨论】:

    猜你喜欢
    • 2021-08-04
    • 1970-01-01
    • 2011-10-29
    • 1970-01-01
    • 1970-01-01
    • 2018-08-30
    • 1970-01-01
    • 2020-06-17
    • 2020-02-27
    相关资源
    最近更新 更多