Пример #1
0
        // Constructs a List with a given initial capacity. The list is
        // initially empty, but will have room for the given number of elements
        // before any reallocations are required.
        //
        public LowLevelList(int capacity)
        {
            if (capacity < 0)
            {
                throw new ArgumentOutOfRangeException("capacity");
            }
            Contract.EndContractBlock();

            if (capacity == 0)
            {
                _items = Array_.Empty <T>();
            }
            else
            {
                _items = new T[capacity];
            }
        }
Пример #2
0
        // Constructs a List, copying the contents of the given collection. The
        // size and capacity of the new list will both be equal to the size of the
        // given collection.
        //
        public LowLevelList(IEnumerable <T> collection)
        {
            if (collection == null)
            {
                throw new ArgumentNullException("collection");
            }
            Contract.EndContractBlock();

            ICollection <T> c = collection as ICollection <T>;

            if (c != null)
            {
                int count = c.Count;
                if (count == 0)
                {
                    _items = Array_.Empty <T>();
                }
                else
                {
                    _items = new T[count];
                    c.CopyTo(_items, 0);
                    _size = count;
                }
            }
            else
            {
                _size  = 0;
                _items = Array_.Empty <T>();
                // This enumerable could be empty.  Let Add allocate a new array, if needed.
                // Note it will also go to _defaultCapacity first, not 1, then 2, etc.

                using (IEnumerator <T> en = collection.GetEnumerator())
                {
                    while (en.MoveNext())
                    {
                        Add(en.Current);
                    }
                }
            }
        }
Пример #3
0
 // Constructs a List. The list is initially empty and has a capacity
 // of zero. Upon adding the first element to the list the capacity is
 // increased to 16, and then increased in multiples of two as required.
 public LowLevelList()
 {
     _items = Array_.Empty <T>();
 }
Пример #4
0
        /// <summary>Converts an enumerable to an array using the same logic as does List{T}.</summary>
        /// <param name="length">The number of items stored in the resulting array, 0-indexed.</param>
        /// <returns>
        /// The resulting array.  The length of the array may be greater than <paramref name="length"/>,
        /// which is the actual number of elements in the array.
        /// </returns>
        internal static T[] ToArray <T>(IEnumerable <T> source, out int length)
        {
            T[] arr;
            int count = 0;

            ICollection <T> ic = source as ICollection <T>;

            if (ic != null)
            {
                count = ic.Count;
                if (count == 0)
                {
                    arr = Array_.Empty <T>();
                }
                else
                {
                    // Allocate an array of the desired size, then copy the elements into it. Note that this has the same
                    // issue regarding concurrency as other existing collections like List<T>. If the collection size
                    // concurrently changes between the array allocation and the CopyTo, we could end up either getting an
                    // exception from overrunning the array (if the size went up) or we could end up not filling as many
                    // items as 'count' suggests (if the size went down).  This is only an issue for concurrent collections
                    // that implement ICollection<T>, which as of .NET 4.6 is just ConcurrentDictionary<TKey, TValue>.
                    arr = new T[count];
                    ic.CopyTo(arr, 0);
                }
            }
            else
            {
                arr = Array_.Empty <T>();
                foreach (var item in source)
                {
                    if (count == arr.Length)
                    {
                        // MaxArrayLength is defined in Array.MaxArrayLength and in gchelpers in CoreCLR.
                        // It represents the maximum number of elements that can be in an array where
                        // the size of the element is greater than one byte; a separate, slightly larger constant,
                        // is used when the size of the element is one.
                        const int MaxArrayLength = 0x7FEFFFFF;

                        // This is the same growth logic as in List<T>:
                        // If the array is currently empty, we make it a default size.  Otherwise, we attempt to
                        // double the size of the array.  Doubling will overflow once the size of the array reaches
                        // 2^30, since doubling to 2^31 is 1 larger than Int32.MaxValue.  In that case, we instead
                        // constrain the length to be MaxArrayLength (this overflow check works because of of the
                        // cast to uint).  Because a slightly larger constant is used when T is one byte in size, we
                        // could then end up in a situation where arr.Length is MaxArrayLength or slightly larger, such
                        // that we constrain newLength to be MaxArrayLength but the needed number of elements is actually
                        // larger than that.  For that case, we then ensure that the newLength is large enough to hold
                        // the desired capacity.  This does mean that in the very rare case where we've grown to such a
                        // large size, each new element added after MaxArrayLength will end up doing a resize.
                        const int DefaultCapacity = 4;
                        int       newLength       = count == 0 ? DefaultCapacity : count * 2;
                        if ((uint)newLength > MaxArrayLength)
                        {
                            newLength = MaxArrayLength;
                        }
                        if (newLength < count + 1)
                        {
                            newLength = count + 1;
                        }

                        Array.Resize(ref arr, newLength);
                    }
                    arr[count++] = item;
                }
            }

            length = count;
            return(arr);
        }