C# net从两个对象列表创建列表-性能差异

C# net从两个对象列表创建列表-性能差异,c#,.net,list,linq,C#,.net,List,Linq,我想知道这两种从2个(或更多)对象列表创建列表的方法在性能上是否有差异 我这样问是因为作为一个初学者,我用方法2对大多数情况进行了编码(在许多小项目中),所以我想知道是否应该用方法1替换方法2 举例如下: 方式1: var mergedList=new List<Person>(); mergeList.AddRange(list1); mergeList.AddRange(list2); var mergedList=new List(); mergeList.AddRange(

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

我这样问是因为作为一个初学者,我用方法2对大多数情况进行了编码(在许多小项目中),所以我想知道是否应该用方法1替换方法2

举例如下:

方式1:

var mergedList=new List<Person>();
mergeList.AddRange(list1);
mergeList.AddRange(list2);
var mergedList=new List();
mergeList.AddRange(列表1);
mergeList.AddRange(列表2);
方式2:

var mergedList=new List<Person>();

foreach(var item in list1)
{
    mergedList.Add(item);
}
foreach(var item in list2)
{
     mergedList.Add(item);
}
var mergedList=new List();
foreach(列表1中的变量项)
{
合并列表。添加(项);
}
foreach(列表2中的变量项)
{
合并列表。添加(项);
}

好吧,您可能不会注意到有什么不同,所以您使用循环的旧方法非常好。但是使用方法1,您可以节省几行代码。确实可以更高效一点,因为当您传递一个类型(具有一个数组)时,它可以用正确的大小初始化列表(以及作为数组的底层存储)。如果数组未初始化为正确的大小,则必须在循环中调整其大小

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

public void InsertRange(int索引,IEnumerable集合){
// ...
ICollection c=作为ICollection的集合;
如果(c!=null){//如果集合是ICollection
//如果将AddRange与列表一起使用,则这是优化版本
int计数=c计数;
如果(计数>0){
确保资本充足率(_大小+数量);
如果(索引大小){
复制(_项,索引,_项,索引+计数,_大小-索引);
}
//如果我们在列表中插入一个列表,我们希望能够处理这个问题。
if(this==c){
//将_项的第一部分复制到插入位置
复制(_项,0,_项,索引,索引);
//将_项的最后一部分复制回插入位置
数组.Copy(_项,索引+计数,_项,索引*2,_大小-索引);
}
否则{
T[]itemsToInsert=新的T[计数];
c、 CopyTo(itemsToInsert,0);
itemsToInsert.CopyTo(_items,index);
}
_大小+=计数;
}                
}
否则{
//这是您使用的循环版本
使用(IEnumerator en=collection.GetEnumerator()){
while(en.MoveNext()){
插入(索引++,当前版本);
}                
}
}
_版本++;
}

将回答另一个问题,作为高级语言的开发人员,您应该对代码的简单性感兴趣。如果您有性能问题,请尝试解决它


您的代码也会这样做,您不会注意到任何性能差异=)

有些东西是马,有些东西是赛跑。您是否尝试过任何性能监控?这又是一个关于“不要寻找没有问题的问题”的问题。或者换句话说:。话虽如此,除非您有强烈的需求,否则您根本不应该用另一个替换所有出现的一个。List确实有一个构造函数,其容量作为参数。它是内部阵列中保留的插槽数量。列表以10的容量开始,如果在上面添加项,则每次都必须重新创建内部数组并复制现有项。在您的情况下,您知道要插入的列表的大小,因此您可以使用list1.Count+list2.Count的容量初始化合并列表。感谢您提供的好答案和无毒性。
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++;            
}