High memory consumption with Enumerable.Range?

前端 未结 4 637
轻奢々
轻奢々 2020-11-28 16:03

Originally i wanted to know whether ToList allocates more memory than using the constructor of List which takes an IEnumerable

4条回答
  •  佛祖请我去吃肉
    2020-11-28 16:39

    It's because of the doubling algorithm used to create the backing array in a List. IEnumerable has no Count property so it can't pre-allocate the backing array to be the target size when you call ToList. In fact, on each call to MoveNext you are calling a corresponding Add on the List.

    However Array.ToList can override the base ToList behaviour to initialise the list to the correct capacity. Also, it could be the List in it's constructor which tries to downcast the IEnumerable reference it has to known collection types such as IList, ICollection, Array, etc...

    Update

    In fact it is in the constructor of List that it figures out if the argument implements ICollection:

    public List(IEnumerable collection)
    {
      if (collection == null)
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
      ICollection collection1 = collection as ICollection;
      if (collection1 != null)
      {
        int count = collection1.Count;
        if (count == 0)
        {
          this._items = List._emptyArray;
        }
        else
        {
          this._items = new T[count];
          collection1.CopyTo(this._items, 0);
          this._size = count;
        }
      }
      else
      {
        this._size = 0;
        this._items = List._emptyArray;
        foreach (T obj in collection)
          this.Add(obj);
      }
    }
    

提交回复
热议问题