linq-ToList
public class MyList{ private int _size; internal T[] _items; // Do not rename (binary serialization) private static readonly T[] s_emptyArray = new T[0]; private int _version; // Do not rename (binary serialization) private const int DefaultCapacity = 4; public MyList(IEnumerable collection) { if (collection == null) //ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); if (collection is ICollection c) { int count = c.Count; if (count == 0) { _items = s_emptyArray; } else { _items = new T[count]; c.CopyTo(_items, 0); _size = count; } } else { _items = s_emptyArray; using (IEnumerator en = collection?.GetEnumerator()) { while (en.MoveNext()) { Add(en.Current); } } } } // Adds the given object to the end of this list. The size of the list is // increased by one. If required, the capacity of the list is doubled // before adding the new element. // 如果需要,列表的容量将增加一倍 // 在添加新元素之前。 [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Add(T item) { _version++; T[] array = _items; int size = _size; if ((uint)size < (uint)array.Length) { _size = size + 1; array[size] = item; } else { AddWithResize(item); } } // Non-inline from List.Add to improve its code quality as uncommon path // 列表中的非内联。添加以提高其代码质量 [MethodImpl(MethodImplOptions.NoInlining)] private void AddWithResize(T item) { Debug.Assert(_size == _items.Length); int size = _size; Grow(size + 1); _size = size + 1; _items[size] = item; } /// /// Increase the capacity of this list to at least the specified . /// 将此列表的容量至少增加到指定的 。 /// /// The minimum capacity to ensure. private void Grow(int capacity) { Debug.Assert(_items.Length < capacity); int newcapacity = _items.Length == 0 ? DefaultCapacity : 2 * _items.Length; // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow. // Note that this check works even when _items.Length overflowed thanks to the (uint) cast // 在遇到溢出之前,允许列表增长到最大可能容量(~2G个元素)。 // 请注意,即使由于(uint)强制转换而导致_items.Length溢出,此检查仍有效 // Array.MaxLength if ((uint)newcapacity > 0X7FFFFFC7) newcapacity = 0X7FFFFFC7; // If the computed capacity is still less than specified, set to the original argument. // Capacities exceeding Array.MaxLength will be surfaced as OutOfMemoryException by Array.Resize. //如果计算的容量仍然小于指定的容量,请设置为原始参数。 //超过Array.MaxLength的容量将由Array.Resize显示为OutOfMemoryException。 if (newcapacity < capacity) newcapacity = capacity; Capacity = newcapacity; } // Gets and sets the capacity of this list. The capacity is the size of // the internal array used to hold items. When set, the internal // array of the list is reallocated to the given capacity. // 获取并设置此列表的容量。容量是指容量的大小 // 用于保存项目的内部数组。设置后,内部 // 列表的数组被重新分配到给定的容量。 public int Capacity { get => _items.Length; set { if (value < _size) { //ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity); } if (value != _items.Length) { if (value > 0) { T[] newItems = new T[value]; if (_size > 0) { Array.Copy(_items, newItems, _size); } _items = newItems; } else { _items = s_emptyArray; } } } } }
具体实现:
String[] languages = { "c++", "Java", "C#", "VB.net", "VC.net", "PHP", "Python", "GO" }; //var query = from item in languages // group item by item.Length into lengthGroups // orderby lengthGroups.Key // select lengthGroups; //var query2 = languages.ToLookup(x => x.Length); //foreach (var item in query2) //{ // Console.WriteLine(item.Key); // foreach (var lengthGroupItem in item) // { // Console.WriteLine(lengthGroupItem); // } //} MyListmyList = new MyList<string>(languages);
源码中主要内存分配的优化,add的实现是array[index] = value;