Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
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
85 changes: 85 additions & 0 deletions src/Common/src/System/Collections/Generic/EnumerableHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace System.Collections.Generic
{
/// <summary>Internal helper functions for working with enumerables.</summary>
internal static class EnumerableHelpers
{
/// <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;
}

arr = ArrayT<T>.Resize(arr, newLength, count);
}
arr[count++] = item;
}
}

length = count;
return arr;
}
}
}
7 changes: 5 additions & 2 deletions src/System.Collections/src/System.Collections.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,14 @@
<Compile Include="System\Collections\StructuralComparisons.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="$(CommonPath)\System\ArrayT.cs">
<Link>Common\System\ArrayT.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\System\Collections\HashHelpers.cs">
<Link>Common\System\Collections\HashHelpers.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\System\ArrayT.cs">
<Link>Common\System\ArrayT.cs</Link>
<Compile Include="$(CommonPath)\System\Collections\Generic\EnumerableHelpers.cs">
<Link>Common\System\Collections\Generic\EnumerableHelpers.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,13 @@ public class Queue<T> : IEnumerable<T>,
private const int MinimumGrow = 4;
private const int GrowFactor = 200; // double each time
private const int DefaultCapacity = 4;
private static T[] s_emptyArray = Array.Empty<T>();

// Creates a queue with room for capacity objects. The default initial
// capacity and grow factor are used.
/// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.Queue"]/*' />
public Queue()
{
_array = s_emptyArray;
_array = Array.Empty<T>();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 this should probably have been part of a different commit.

}

// Creates a queue with room for capacity objects. The default grow factor
Expand All @@ -50,11 +49,7 @@ public Queue(int capacity)
{
if (capacity < 0)
throw new ArgumentOutOfRangeException("capacity", SR.ArgumentOutOfRange_NeedNonNegNumRequired);

_array = new T[capacity];
_head = 0;
_tail = 0;
_size = 0;
}

// Fills a Queue with the elements of an ICollection. Uses the enumerator
Expand All @@ -67,8 +62,6 @@ public Queue(IEnumerable<T> collection)
throw new ArgumentNullException("collection");

_array = new T[DefaultCapacity];
_size = 0;
_version = 0;

using (IEnumerator<T> en = collection.GetEnumerator())
{
Expand Down
52 changes: 25 additions & 27 deletions src/System.Collections/src/System/Collections/Generic/SortedSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,9 @@ public SortedSet(IEnumerable<T> collection, IComparer<T> comparer)
//breadth first traversal to recreate nodes
if (baseSortedSet.Count == 0)
{
_count = 0;
_version = 0;
_root = null;
return;
}


//pre order way to replicate nodes
Stack<Node> theirStack = new Stack<SortedSet<T>.Node>(2 * log2(baseSortedSet.Count) + 2);
Stack<Node> myStack = new Stack<SortedSet<T>.Node>(2 * log2(baseSortedSet.Count) + 2);
Expand Down Expand Up @@ -138,23 +134,27 @@ public SortedSet(IEnumerable<T> collection, IComparer<T> comparer)
}
}
_count = baseSortedSet._count;
_version = 0;
}
else
{ //As it stands, you're doing an NlogN sort of the collection
List<T> els = new List<T>(collection);
els.Sort(_comparer);
for (int i = 1; i < els.Count; i++)
{
int count;
T[] els = EnumerableHelpers.ToArray(collection, out count);
if (count > 0)
{
if (comparer.Compare(els[i], els[i - 1]) == 0)
Array.Sort(els, 0, count, _comparer);
int index = 1;
for (int i = 1; i < count; i++)
{
els.RemoveAt(i);
i--;
if (comparer.Compare(els[i], els[i - 1]) != 0)
{
els[index++] = els[i];
}
}
count = index;

_root = ConstructRootFromSortedArray(els, 0, count - 1, null);
_count = count;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You no longer need to set the version?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the constructor. Setting _version to 0 here is redundant because the CLR initializes all fields to their default values.

_root = ConstructRootFromSortedArray(els.ToArray(), 0, els.Count - 1, null);
_count = els.Count;
_version = 0;
}
}

Expand Down Expand Up @@ -257,25 +257,24 @@ internal virtual bool BreadthFirstTreeWalk(TreeWalkPredicate<T> action)
return true;
}

List<Node> processQueue = new List<Node>();
processQueue.Add(_root);
Queue<Node> processQueue = new Queue<Node>();
processQueue.Enqueue(_root);
Node current;

while (processQueue.Count != 0)
{
current = processQueue[0];
processQueue.RemoveAt(0);
current = processQueue.Dequeue();
if (!action(current))
{
return false;
}
if (current.Left != null)
{
processQueue.Add(current.Left);
processQueue.Enqueue(current.Left);
}
if (current.Right != null)
{
processQueue.Add(current.Right);
processQueue.Enqueue(current.Right);
}
}
return true;
Expand Down Expand Up @@ -2084,25 +2083,24 @@ internal override bool BreadthFirstTreeWalk(TreeWalkPredicate<T> action)
return true;
}

List<Node> processQueue = new List<Node>();
processQueue.Add(_root);
Queue<Node> processQueue = new Queue<Node>();
processQueue.Enqueue(_root);
Node current;

while (processQueue.Count != 0)
{
current = processQueue[0];
processQueue.RemoveAt(0);
current = processQueue.Dequeue();
if (IsWithinRange(current.Item) && !action(current))
{
return false;
}
if (current.Left != null && (!_lBoundActive || Comparer.Compare(_min, current.Item) < 0))
{
processQueue.Add(current.Left);
processQueue.Enqueue(current.Left);
}
if (current.Right != null && (!_uBoundActive || Comparer.Compare(_max, current.Item) > 0))
{
processQueue.Add(current.Right);
processQueue.Enqueue(current.Right);
}
}
return true;
Expand Down
30 changes: 2 additions & 28 deletions src/System.Collections/src/System/Collections/Generic/Stack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,11 @@ public class Stack<T> : IEnumerable<T>,
private Object _syncRoot;

private const int DefaultCapacity = 4;
private static T[] s_emptyArray = Array.Empty<T>();

/// <include file='doc\Stack.uex' path='docs/doc[@for="Stack.Stack"]/*' />
public Stack()
{
_array = s_emptyArray;
_size = 0;
_version = 0;
_array = Array.Empty<T>();
}

// Create a stack with a specific initial capacity. The initial capacity
Expand All @@ -47,8 +44,6 @@ public Stack(int capacity)
if (capacity < 0)
throw new ArgumentOutOfRangeException("capacity", SR.ArgumentOutOfRange_NeedNonNegNumRequired);
_array = new T[capacity];
_size = 0;
_version = 0;
}

// Fills a Stack with the contents of a particular collection. The items are
Expand All @@ -59,28 +54,7 @@ public Stack(IEnumerable<T> collection)
{
if (collection == null)
throw new ArgumentNullException("collection");

ICollection<T> c = collection as ICollection<T>;
if (c != null)
{
int count = c.Count;
_array = new T[count];
c.CopyTo(_array, 0);
_size = count;
}
else
{
_size = 0;
_array = new T[DefaultCapacity];

using (IEnumerator<T> en = collection.GetEnumerator())
{
while (en.MoveNext())
{
Push(en.Current);
}
}
}
_array = EnumerableHelpers.ToArray(collection, out _size);
}

/// <include file='doc\Stack.uex' path='docs/doc[@for="Stack.Count"]/*' />
Expand Down