Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply feedback to grow methods of generic collections #49167

Merged
merged 2 commits into from
Mar 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public void Enqueue(T item)
{
if (_size == _array.Length)
{
EnsureCapacityCore(_size + 1);
Grow(_size + 1);
}

_array[_tail] = item;
Expand Down Expand Up @@ -390,38 +390,35 @@ public int EnsureCapacity(int capacity)

if (_array.Length < capacity)
{
EnsureCapacityCore(capacity);
Grow(capacity);
}

return _array.Length;
}

private void EnsureCapacityCore(int capacity)
private void Grow(int capacity)
{
Debug.Assert(capacity >= 0);
Debug.Assert(_array.Length < capacity);

if (_array.Length < capacity)
{
// Array.MaxArrayLength is internal to S.P.CoreLib, replicate here.
const int MaxArrayLength = 0X7FEFFFFF;
const int GrowFactor = 2;
const int MinimumGrow = 4;
// Array.MaxArrayLength is internal to S.P.CoreLib, replicate here.
const int MaxArrayLength = 0X7FEFFFFF;
const int GrowFactor = 2;
const int MinimumGrow = 4;

int newcapacity = GrowFactor * _array.Length;
int newcapacity = GrowFactor * _array.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
if ((uint)newcapacity > MaxArrayLength) newcapacity = MaxArrayLength;
// 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
if ((uint)newcapacity > MaxArrayLength) newcapacity = MaxArrayLength;

// Ensure minimum growth is respected.
newcapacity = Math.Max(newcapacity, _array.Length + MinimumGrow);
// Ensure minimum growth is respected.
newcapacity = Math.Max(newcapacity, _array.Length + MinimumGrow);

// If the computed capacity is still less than specified, set to the original argument.
// Capacities exceeding MaxArrayLength will be surfaced as OutOfMemoryException by Array.Resize.
if (newcapacity < capacity) newcapacity = capacity;
// If the computed capacity is still less than specified, set to the original argument.
// Capacities exceeding MaxArrayLength will be surfaced as OutOfMemoryException by Array.Resize.
if (newcapacity < capacity) newcapacity = capacity;

SetCapacity(newcapacity);
}
SetCapacity(newcapacity);
}

// Implements an enumerator for a Queue. The enumerator uses the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ public void Push(T item)
private void PushWithResize(T item)
{
Debug.Assert(_size == _array.Length);
EnsureCapacityCore(_size + 1);
Grow(_size + 1);
_array[_size] = item;
_version++;
_size++;
Expand All @@ -304,34 +304,31 @@ public int EnsureCapacity(int capacity)

if (_array.Length < capacity)
{
EnsureCapacityCore(capacity);
Grow(capacity);
_version++;
}

return _array.Length;
}

private void EnsureCapacityCore(int capacity)
private void Grow(int capacity)
{
Debug.Assert(capacity >= 0);
Debug.Assert(_array.Length < capacity);

if (_array.Length < capacity)
{
// Array.MaxArrayLength is internal to S.P.CoreLib, replicate here.
const int MaxArrayLength = 0X7FEFFFFF;
// Array.MaxArrayLength is internal to S.P.CoreLib, replicate here.
const int MaxArrayLength = 0X7FEFFFFF;

int newcapacity = _array.Length == 0 ? DefaultCapacity : 2 * _array.Length;
int newcapacity = _array.Length == 0 ? DefaultCapacity : 2 * _array.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.
if ((uint)newcapacity > MaxArrayLength) newcapacity = MaxArrayLength;
// 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.
if ((uint)newcapacity > MaxArrayLength) newcapacity = MaxArrayLength;

// If computed capacity is still less than specified, set to the original argument.
// Capacities exceeding MaxArrayLength will be surfaced as OutOfMemoryException by Array.Resize.
if (newcapacity < capacity) newcapacity = capacity;
// If computed capacity is still less than specified, set to the original argument.
// Capacities exceeding MaxArrayLength will be surfaced as OutOfMemoryException by Array.Resize.
if (newcapacity < capacity) newcapacity = capacity;

Array.Resize(ref _array, newcapacity);
}
Array.Resize(ref _array, newcapacity);
}

// Copies the Stack to an array, in the same order Pop would return the items.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,9 @@ public void Add(T item)
[MethodImpl(MethodImplOptions.NoInlining)]
private void AddWithResize(T item)
{
Debug.Assert(_size == _items.Length);
int size = _size;
EnsureCapacityCore(size + 1);
Grow(size + 1);
_size = size + 1;
_items[size] = item;
}
Expand Down Expand Up @@ -405,35 +406,32 @@ public int EnsureCapacity(int capacity)
}
if (_items.Length < capacity)
{
EnsureCapacityCore(capacity);
Grow(capacity);
_version++;
}

return _items.Length;
}

/// <summary>
/// Increase the capacity of this list to at least the specified <paramref name="capacity"/> by continuously twice current capacity.
/// Increase the capacity of this list to at least the specified <paramref name="capacity"/>.
/// </summary>
/// <param name="capacity">The minimum capacity to ensure.</param>
private void EnsureCapacityCore(int capacity)
private void Grow(int capacity)
{
Debug.Assert(capacity >= 0);
Debug.Assert(_items.Length < capacity);

if (_items.Length < capacity)
{
int newcapacity = _items.Length == 0 ? DefaultCapacity : 2 * _items.Length;
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
if ((uint)newcapacity > Array.MaxArrayLength) newcapacity = Array.MaxArrayLength;
// 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
if ((uint)newcapacity > Array.MaxArrayLength) newcapacity = Array.MaxArrayLength;

// If the computed capacity is still less than specified, set to the original argument.
// Capacities exceeding MaxArrayLength will be surfaced as OutOfMemoryException by Array.Resize.
if (newcapacity < capacity) newcapacity = capacity;
// If the computed capacity is still less than specified, set to the original argument.
// Capacities exceeding MaxArrayLength will be surfaced as OutOfMemoryException by Array.Resize.
if (newcapacity < capacity) newcapacity = capacity;

Capacity = newcapacity;
}
Capacity = newcapacity;
}

public bool Exists(Predicate<T> match)
Expand Down Expand Up @@ -695,7 +693,7 @@ public void Insert(int index, T item)
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_ListInsert);
}
if (_size == _items.Length) EnsureCapacityCore(_size + 1);
if (_size == _items.Length) Grow(_size + 1);
if (index < _size)
{
Array.Copy(_items, index, _items, index + 1, _size - index);
Expand Down Expand Up @@ -741,7 +739,10 @@ public void InsertRange(int index, IEnumerable<T> collection)
int count = c.Count;
if (count > 0)
{
EnsureCapacityCore(_size + count);
if (_items.Length - _size < count)
{
Grow(_size + count);
}
if (index < _size)
{
Array.Copy(_items, index, _items, index + count, _size - index);
Expand Down