-2

I would like to know if there's a difference in performance between these 2 ways to create a list from 2 (or more) objects list.

I'm asking because as a beginer, I coded most of the situations using the way 2 (in many small projects) so I would like to know if I should replace method 2 with method 1.

Examples taken from: Create a list from two object lists with linq

Way 1:

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

Way 2:

var mergedList=new List<Person>();

foreach(var item in list1)
{
    mergedList.Add(item);
}
foreach(var item in list2)
{
     mergedList.Add(item);
}
Koni
  • 452
  • 1
  • 7
  • 19
  • 4
    Something something horses, something something race them. Have you tried any performance monitoring? – David Pilkington Jan 16 '18 at 13:23
  • 1
    And once again a question for https://ericlippert.com/2012/12/17/performance-rant/ Don´t hunt for problems that are none. Or in other words: ["premature optimization is the root of all evil"](http://wiki.c2.com/?PrematureOptimization). Having said this, you should´t replace all occurences of the one by the other at all, unless you have strong need to do so. – MakePeaceGreatAgain Jan 16 '18 at 13:27
  • List does have a constructor with capacity as a parameter. Its the amount of slots reserved in the internal array. Lists start with a capacity of 10, if you add items above, the internal array has to be recreated and the existing items copied each time. In your case you know the size of the lists you want to insert, so you can initialize the merged list with a capacity of list1.Count + list2.Count. – Otterprinz Jan 16 '18 at 13:42

2 Answers2

1

Well, you probably won't notice a difference, so your old way with loops is perfectly fine. But with way 1 you can save few lines of code. List.AddRange can indeed be a little bit more efficient because it can initialize the list (and the underlying storage which is an array) with the correct size when you pass a type which is a collection(has a Count property). If the array is not initialized with the correct size it must be resized in the loop.

You can see the optimization approach in the source(InsertRange called from 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++;            
}
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
1

Will answer to other question, as developer of highlevel language, you should be interested in simplicity of your code. If you have issues with performance - then try to resolve it!

Your code doing the same, and you will not notice any performance difference =)