What is the best way to modify a list in a 'foreach' loop?

前端 未结 11 752
不思量自难忘°
不思量自难忘° 2020-11-22 05:23

A new feature in C# / .NET 4.0 is that you can change your enumerable in a foreach without getting the exception. See Paul Jackson\'s blog entry An Interest

11条回答
  •  被撕碎了的回忆
    2020-11-22 06:05

    The best approach from a performance perspective is probably to use a one or two arrays. Copy the list to an array, do operations on the array, and then build a new list from the array. Accessing an array element is faster than accessing a list item, and conversions between a List and a T[] can use a fast "bulk copy" operation which avoids the overhead associated accessing individual items.

    For example, suppose you have a List and wish to have every string in the list which starts with T be followed by an item "Boo", while every string that starts with "U" is dropped entirely. An optimal approach would probably be something like:

    int srcPtr,destPtr;
    string[] arr;
    
    srcPtr = theList.Count;
    arr = new string[srcPtr*2];
    theList.CopyTo(arr, theList.Count); // Copy into second half of the array
    destPtr = 0;
    for (; srcPtr < arr.Length; srcPtr++)
    {
      string st = arr[srcPtr];
      char ch = (st ?? "!")[0]; // Get first character of string, or "!" if empty
      if (ch != 'U')
        arr[destPtr++] = st;
      if (ch == 'T')
        arr[destPtr++] = "Boo";
    }
    if (destPtr > arr.Length/2) // More than half of dest. array is used
    {
      theList = new List(arr); // Adds extra elements
      if (destPtr != arr.Length)
        theList.RemoveRange(destPtr, arr.Length-destPtr); // Chop to proper length
    }
    else
    {
      Array.Resize(ref arr, destPtr);
      theList = new List(arr); // Adds extra elements
    }
    

    It would have been helpful if List provided a method to construct a list from a portion of an array, but I'm unaware of any efficient method for doing so. Still, operations on arrays are pretty fast. Of note is the fact that adding and removing items from the list does not require "pushing" around other items; each item gets written directly to its appropriate spot in the array.

提交回复
热议问题