Copying a list to a new list is more efficient and best practice.

What is the appropriate way to copy a list to a new list? And What is the most efficient way to copy a list to a new list?

Efficiency, not code efficiency, is more in the context of the concept behind the scenes.

List<String>List2 = List.ToList(); 

Or:

 List<String>List2 = new List<String>(); foreach (string item in List) { List2.Add(item); } 

Update:

What about a more efficient IL code?

+4
source share
6 answers

What ToList does (abbreviated):

 public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source) { return new List<TSource>(source); } 

Which ctor list does (shorten):

 public List(IEnumerable<T> collection) { ICollection<T> collection2 = collection as ICollection<T>; int count = collection2.Count; this._items = new T[count]; collection2.CopyTo(this._items, 0); this._size = count; } 

Thus, ToList () is much more efficient - it first allocates space, and then copies all the elements in one step.

+6
source

Given that List<T> has an IEnumerable<T> constructor, I would prefer this form:

 List<string> newList = new List<string>(otherList); 

Edit

And as Ondrej points out in the decompiled code below, the List<T> constructor determines the size of the array and copies the contents. This will be much faster than creating a new list, and then repeating another list adding the elements individually, especially since in your second example you did not specify how many elements should be distributed.

+13
source

You can use the List<T> constructor , which takes an IEnumerable<T>

 List<string> list1 = new List<string>(); // fill list1 List<string> list2 = new List<string>(list1); 
+4
source

In terms of efficiency, the first will be faster. List<T> base implementation is an ArrayList, so you have to resize the base array when you call .Add .

On the other hand, .ToList can determine the correct initial size of the new List and avoid the redistribution operation from which the foreach technique suffers.

With that in mind, I would recommend .ToList . Less code and it will be faster.

Here is a simple program that you can run to make sure ToList really faster:

 void Main() { List<int> items = new List<int>(); items = Enumerable.Range(0, 1000000).ToList(); CopyWithToList(items); CopyWithForeach(items); } public void CopyWithToList<T>(List<T> list) { var sw = Stopwatch.StartNew(); List<T> copy = list.ToList(); sw.Stop(); Console.WriteLine("CopyWithToList: {0}", sw.Elapsed); } public void CopyWithForeach<T>(List<T> list) { var sw = Stopwatch.StartNew(); List<T> copy = new List<T>(); foreach (T item in list) { copy.Add(item); } sw.Stop(); Console.WriteLine("CopyWithForeach: {0}", sw.Elapsed); } 
+2
source

I believe the two examples are identical, then .ToList () implements probably a later one.

The best performance would be something like this:

 List<String> list2 = new List<String>(list.Count); foreach(String item in list) list2.Add(item); 

An important part is to create a list2 with enough capacity to store its contents.

If you do not need to subsequently modify one of these lists, you only need a reference copy:

 List<String> list2 = list; 
+1
source

Tests show that .ToList() method has the best performance (for a list with elements 21474836, it works after about 48 ms on a Core i5 processor for a laptop).

Every other method is slower, and a method using .Add() is the worst in terms of performance.

Here are some test codes:

 class Program { static void Main() { var list = new List<int>(); for (int i = 0; i < int.MaxValue / 100; i++) { list.Add(i); } TimeItAccurate(ListCopy_1, list, 10); TimeItAccurate(ListCopy_2, list, 10); TimeItAccurate(ListCopy_3, list, 10); TimeItAccurate(ListCopy_4, list, 10); TimeItAccurate(ListCopy_5, list, 10); } private static List<int> ListCopy_1(List<int> list) { var newList = list.ToList(); return newList; } private static List<int> ListCopy_2(List<int> list) { var newList = new List<int>(list.Count); foreach (var i in list) { newList.Add(i); } return newList; } private static List<int> ListCopy_3(List<int> list) { var newList = new List<int>(list.ToArray()); return newList; } private static List<int> ListCopy_4(List<int> list) { var newList = new List<int>(list.Count); newList.AddRange(list); return newList; } private static List<int> ListCopy_5(List<int> list) { var newList = new List<int>(list); return newList; } public static void TimeItAccurate<TIn, TResult>(Func<TIn, TResult> func, TIn argument, int iterationsCount) { #region Pre-heat for (int i = 0; i < 10; i++) { var t = func.Invoke(argument); } #endregion var stopwatch = new Stopwatch(); var result = default(TResult); stopwatch.Start(); for (int i = 0; i < iterationsCount; i++) { result = func.Invoke(argument); } stopwatch.Stop(); Console.WriteLine("Result:\n{4}(...) == {0}\n\n{1} iterations done in {2} ms.\nAverage time: {3:f5} ms.", result, iterationsCount, stopwatch.ElapsedMilliseconds, stopwatch.ElapsedMilliseconds / (double)iterationsCount, func.Method.Name); } } 

And the results:

 Result (.ToList()): ListCopy_1(...) == System.Collections.Generic.List`1[System.Int32] 10 iterations done in 474 ms. Average time: 47.40000 ms. Result (for-cycle with .Add()): ListCopy_2(...) == System.Collections.Generic.List`1[System.Int32] 10 iterations done in 1896 ms. Average time: 189.60000 ms. Result (ctor with .ToArray()): ListCopy_3(...) == System.Collections.Generic.List`1[System.Int32] 10 iterations done in 981 ms. Average time: 98.10000 ms. Result (.AddRange()): ListCopy_4(...) == System.Collections.Generic.List`1[System.Int32] 10 iterations done in 959 ms. Average time: 95.90000 ms. Result (new List<int>(list)): ListCopy_5(...) == System.Collections.Generic.List`1[System.Int32] 10 iterations done in 480 ms. Average time: 48.00000 ms. 
+1
source

Source: https://habr.com/ru/post/1490712/


All Articles