diff options
author | Stephen Toub <stoub@microsoft.com> | 2017-01-04 02:22:53 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-04 02:22:53 +0300 |
commit | 67414d80dc82f933c9d45beb2d1e9cabac430162 (patch) | |
tree | 156d62f5fc77f35bcb5b9e2bcae1191f9dd05c2b /src | |
parent | 8dc68d828c1d0478e1390a7d83367b5806894b7d (diff) | |
parent | 171b6629e4875fd837308a0cc3f264b4cc6ba99a (diff) |
Merge pull request #14537 from jamesqo/more-xml-docs
Add XML docs to some Linq iterators
Diffstat (limited to 'src')
-rw-r--r-- | src/System.Linq/src/System/Linq/AppendPrepend.cs | 49 | ||||
-rw-r--r-- | src/System.Linq/src/System/Linq/Buffer.cs | 15 | ||||
-rw-r--r-- | src/System.Linq/src/System/Linq/Concat.cs | 21 | ||||
-rw-r--r-- | src/System.Linq/src/System/Linq/Distinct.cs | 4 | ||||
-rw-r--r-- | src/System.Linq/src/System/Linq/Iterator.cs | 75 | ||||
-rw-r--r-- | src/System.Linq/src/System/Linq/Partition.cs | 69 | ||||
-rw-r--r-- | src/System.Linq/src/System/Linq/Range.cs | 3 | ||||
-rw-r--r-- | src/System.Linq/src/System/Linq/Repeat.cs | 4 | ||||
-rw-r--r-- | src/System.Linq/src/System/Linq/Reverse.cs | 4 | ||||
-rw-r--r-- | src/System.Linq/src/System/Linq/Select.cs | 30 | ||||
-rw-r--r-- | src/System.Linq/src/System/Linq/Set.cs | 89 | ||||
-rw-r--r-- | src/System.Linq/src/System/Linq/Union.cs | 14 | ||||
-rw-r--r-- | src/System.Linq/src/System/Linq/Utilities.cs | 29 | ||||
-rw-r--r-- | src/System.Linq/src/System/Linq/Where.cs | 27 |
14 files changed, 374 insertions, 59 deletions
diff --git a/src/System.Linq/src/System/Linq/AppendPrepend.cs b/src/System.Linq/src/System/Linq/AppendPrepend.cs index c5ae31b201..e1cf0cf6c5 100644 --- a/src/System.Linq/src/System/Linq/AppendPrepend.cs +++ b/src/System.Linq/src/System/Linq/AppendPrepend.cs @@ -41,6 +41,10 @@ namespace System.Linq return new AppendPrepend1Iterator<TSource>(source, element, false); } + /// <summary> + /// Represents the insertion of one or more items before or after an <see cref="IEnumerable{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source enumerable.</typeparam> private abstract class AppendPrependIterator<TSource> : Iterator<TSource>, IIListProvider<TSource> { protected readonly IEnumerable<TSource> _source; @@ -92,6 +96,10 @@ namespace System.Linq public abstract int GetCount(bool onlyIfCheap); } + /// <summary> + /// Represents the insertion of an item before or after an <see cref="IEnumerable{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source enumerable.</typeparam> private class AppendPrepend1Iterator<TSource> : AppendPrependIterator<TSource> { private readonly TSource _item; @@ -260,8 +268,17 @@ namespace System.Linq } } + /// <summary> + /// An immutable node in a singly-linked list of items. + /// </summary> + /// <typeparam name="TSource">The type of the node's item.</typeparam> private sealed class SingleLinkedNode<TSource> { + /// <summary> + /// Constructs a node linked to the tail node. + /// </summary> + /// <param name="first">The first item, to be placed in the tail node.</param> + /// <param name="second">The second item, to be placed in this node.</param> public SingleLinkedNode(TSource first, TSource second) { Linked = new SingleLinkedNode<TSource>(first); @@ -269,12 +286,21 @@ namespace System.Linq Count = 2; } + /// <summary> + /// Constructs a tail node. + /// </summary> + /// <param name="item">The item to place in the tail node.</param> public SingleLinkedNode(TSource item) { Item = item; Count = 1; } + /// <summary> + /// Constructs a node linked to the specified node. + /// </summary> + /// <param name="linked">The linked node.</param> + /// <param name="item">The item to place in this node.</param> private SingleLinkedNode(SingleLinkedNode<TSource> linked, TSource item) { Debug.Assert(linked != null); @@ -283,19 +309,38 @@ namespace System.Linq Count = linked.Count + 1; } + /// <summary> + /// The item held by this node. + /// </summary> public TSource Item { get; } + /// <summary> + /// The next node in the singly-linked list. + /// </summary> public SingleLinkedNode<TSource> Linked { get; } + /// <summary> + /// The number of items stored in this and subsequent nodes. + /// </summary> public int Count { get; } + /// <summary> + /// Creates a new node that holds the specified item and is linked to this node. + /// </summary> + /// <param name="item">The item to place in the new node.</param> public SingleLinkedNode<TSource> Add(TSource item) => new SingleLinkedNode<TSource>(this, item); + /// <summary> + /// Gets an <see cref="IEnumerator{TSource}"/> that enumerates the items of this node's singly-linked list in reverse. + /// </summary> public IEnumerator<TSource> GetEnumerator() { return ((IEnumerable<TSource>)ToArray()).GetEnumerator(); } + /// <summary> + /// Returns an <see cref="T:TSource[]"/> that contains the items of this node's singly-linked list in reverse. + /// </summary> public TSource[] ToArray() { TSource[] array = new TSource[Count]; @@ -311,6 +356,10 @@ namespace System.Linq } } + /// <summary> + /// Represents the insertion of multiple items before or after an <see cref="IEnumerable{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source enumerable.</typeparam> private class AppendPrependN<TSource> : AppendPrependIterator<TSource> { private readonly SingleLinkedNode<TSource> _prepended; diff --git a/src/System.Linq/src/System/Linq/Buffer.cs b/src/System.Linq/src/System/Linq/Buffer.cs index 839e1450fb..16d5cc1ee4 100644 --- a/src/System.Linq/src/System/Linq/Buffer.cs +++ b/src/System.Linq/src/System/Linq/Buffer.cs @@ -6,11 +6,26 @@ using System.Collections.Generic; namespace System.Linq { + /// <summary> + /// A buffer into which the contents of an <see cref="IEnumerable{TElement}"/> can be stored. + /// </summary> + /// <typeparam name="TElement">The type of the buffer's elements.</typeparam> internal struct Buffer<TElement> { + /// <summary> + /// The stored items. + /// </summary> internal readonly TElement[] _items; + + /// <summary> + /// The number of stored items. + /// </summary> internal readonly int _count; + /// <summary> + /// Fully enumerates the provided enumerable and stores its items into an array. + /// </summary> + /// <param name="source">The enumerable to be store.</param> internal Buffer(IEnumerable<TElement> source) { IIListProvider<TElement> iterator = source as IIListProvider<TElement>; diff --git a/src/System.Linq/src/System/Linq/Concat.cs b/src/System.Linq/src/System/Linq/Concat.cs index aae66235ad..feda438775 100644 --- a/src/System.Linq/src/System/Linq/Concat.cs +++ b/src/System.Linq/src/System/Linq/Concat.cs @@ -44,6 +44,10 @@ namespace System.Linq return new Concat2EnumerableIterator<TSource>(first, second); } + /// <summary> + /// Represents the concatenation of two <see cref="IEnumerable{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source enumerables.</typeparam> private sealed class Concat2EnumerableIterator<TSource> : ConcatIterator<TSource> { private readonly IEnumerable<TSource> _first; @@ -83,6 +87,11 @@ namespace System.Linq // only have to traverse all of the previous sources once per chained enumerable. An // alternative would be to use an array to store all of the enumerables, but this has // a much better memory profile and without much additional run-time cost. + + /// <summary> + /// Represents the concatenation of three or more <see cref="IEnumerable{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source enumerables.</typeparam> private sealed class ConcatNEnumerableIterator<TSource> : ConcatIterator<TSource> { private readonly ConcatIterator<TSource> _previousConcat; @@ -162,6 +171,10 @@ namespace System.Linq } } + /// <summary> + /// Represents the concatenation of two <see cref="ICollection{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source collections.</typeparam> private sealed class Concat2CollectionIterator<TSource> : ConcatIterator<TSource> { private readonly ICollection<TSource> _first; @@ -232,6 +245,10 @@ namespace System.Linq public override int GetCount(bool onlyIfCheap) => Count; // Getting the count is always cheap. } + /// <summary> + /// Represents the concatenation of three or more <see cref="ICollection{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source collections.</typeparam> private sealed class ConcatNCollectionIterator<TSource> : ConcatIterator<TSource> { private readonly ConcatIterator<TSource> _previous; @@ -387,6 +404,10 @@ namespace System.Linq public override int GetCount(bool onlyIfCheap) => Count; // Getting the count is always cheap relative to manually iterating. } + /// <summary> + /// Represents the concatenation of two or more <see cref="IEnumerable{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source enumerables.</typeparam> private abstract class ConcatIterator<TSource> : Iterator<TSource>, IIListProvider<TSource> { private IEnumerator<TSource> _enumerator; diff --git a/src/System.Linq/src/System/Linq/Distinct.cs b/src/System.Linq/src/System/Linq/Distinct.cs index 054b96b649..65d0a02d6c 100644 --- a/src/System.Linq/src/System/Linq/Distinct.cs +++ b/src/System.Linq/src/System/Linq/Distinct.cs @@ -24,6 +24,10 @@ namespace System.Linq return new DistinctIterator<TSource>(source, comparer); } + /// <summary> + /// An iterator that yields the distinct values in an <see cref="IEnumerable{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source enumerable.</typeparam> private sealed class DistinctIterator<TSource> : Iterator<TSource>, IIListProvider<TSource> { private readonly IEnumerable<TSource> _source; diff --git a/src/System.Linq/src/System/Linq/Iterator.cs b/src/System.Linq/src/System/Linq/Iterator.cs index 7425046e26..27a15c2e42 100644 --- a/src/System.Linq/src/System/Linq/Iterator.cs +++ b/src/System.Linq/src/System/Linq/Iterator.cs @@ -9,30 +9,74 @@ namespace System.Linq { public static partial class Enumerable { + /// <summary> + /// A base class for enumerables that are loaded on-demand. + /// </summary> + /// <typeparam name="TSource">The type of each item to yield.</typeparam> + /// <remarks> + /// <list type="bullet"> + /// <item><description> + /// The value of an iterator is immutable; the operation it represents cannot be changed. + /// </description></item> + /// <item><description> + /// However, an iterator also serves as its own enumerator, so the state of an iterator + /// may change as it is being enumerated. + /// </description></item> + /// <item><description> + /// Hence, state that is relevant to an iterator's value should be kept in readonly fields. + /// State that is relevant to an iterator's enumeration (such as the currently yielded item) + /// should be kept in non-readonly fields. + /// </description></item> + /// </list> + /// </remarks> internal abstract class Iterator<TSource> : IEnumerable<TSource>, IEnumerator<TSource> { private readonly int _threadId; internal int _state; internal TSource _current; + /// <summary> + /// Initializes a new instance of the <see cref="Iterator{TSource}"/> class. + /// </summary> protected Iterator() { _threadId = Environment.CurrentManagedThreadId; } - public TSource Current - { - get { return _current; } - } + /// <summary> + /// The item currently yielded by this iterator. + /// </summary> + public TSource Current => _current; + /// <summary> + /// Makes a shallow copy of this iterator. + /// </summary> + /// <remarks> + /// This method is called if <see cref="GetEnumerator"/> is called more than once. + /// </remarks> public abstract Iterator<TSource> Clone(); + /// <summary> + /// Puts this iterator in a state whereby no further enumeration will take place. + /// </summary> + /// <remarks> + /// Derived classes should override this method if necessary to clean up any + /// mutable state they hold onto (for example, calling Dispose on other enumerators). + /// </remarks> public virtual void Dispose() { _current = default(TSource); _state = -1; } + /// <summary> + /// Gets the enumerator used to yield values from this iterator. + /// </summary> + /// <remarks> + /// If <see cref="GetEnumerator"/> is called for the first time on the same thread + /// that created this iterator, the result will be this iterator. Otherwise, the result + /// will be a shallow copy of this iterator. + /// </remarks> public IEnumerator<TSource> GetEnumerator() { Iterator<TSource> enumerator = _state == 0 && _threadId == Environment.CurrentManagedThreadId ? this : Clone(); @@ -40,27 +84,34 @@ namespace System.Linq return enumerator; } + /// <summary> + /// Retrieves the next item in this iterator and yields it via <see cref="Current"/>. + /// </summary> + /// <returns><c>true</c> if there was another value to be yielded; otherwise, <c>false</c>.</returns> public abstract bool MoveNext(); + /// <summary> + /// Returns an enumerable that maps each item in this iterator based on a selector. + /// </summary> + /// <typeparam name="TResult">The type of the mapped items.</typeparam> + /// <param name="selector">The selector used to map each item.</param> public virtual IEnumerable<TResult> Select<TResult>(Func<TSource, TResult> selector) { return new SelectEnumerableIterator<TSource, TResult>(this, selector); } + /// <summary> + /// Returns an enumerable that filters each item in this iterator based on a predicate. + /// </summary> + /// <param name="predicate">The predicate used to filter each item.</param> public virtual IEnumerable<TSource> Where(Func<TSource, bool> predicate) { return new WhereEnumerableIterator<TSource>(this, predicate); } - object IEnumerator.Current - { - get { return Current; } - } + object IEnumerator.Current => Current; - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); void IEnumerator.Reset() { diff --git a/src/System.Linq/src/System/Linq/Partition.cs b/src/System.Linq/src/System/Linq/Partition.cs index e16af13ad2..2013018a3e 100644 --- a/src/System.Linq/src/System/Linq/Partition.cs +++ b/src/System.Linq/src/System/Linq/Partition.cs @@ -77,40 +77,36 @@ namespace System.Linq TElement TryGetLast(out bool found); } + /// <summary> + /// Represents an enumerable with zero elements. + /// </summary> + /// <typeparam name="TElement">The element type.</typeparam> + /// <remarks> + /// Returning an instance of this type is useful to quickly handle scenarios where it is known + /// that an operation will result in zero elements. + /// </remarks> internal sealed class EmptyPartition<TElement> : IPartition<TElement>, IEnumerator<TElement> { + /// <summary> + /// A cached, immutable instance of an empty enumerable. + /// </summary> public static readonly IPartition<TElement> Instance = new EmptyPartition<TElement>(); private EmptyPartition() { } - public IEnumerator<TElement> GetEnumerator() - { - return this; - } + public IEnumerator<TElement> GetEnumerator() => this; - IEnumerator IEnumerable.GetEnumerator() - { - return this; - } + IEnumerator IEnumerable.GetEnumerator() => this; - public bool MoveNext() - { - return false; - } + public bool MoveNext() => false; [ExcludeFromCodeCoverage] // Shouldn't be called, and as undefined can return or throw anything anyway. - public TElement Current - { - get { return default(TElement); } - } + public TElement Current => default(TElement); [ExcludeFromCodeCoverage] // Shouldn't be called, and as undefined can return or throw anything anyway. - object IEnumerator.Current - { - get { return default(TElement); } - } + object IEnumerator.Current => default(TElement); void IEnumerator.Reset() { @@ -122,15 +118,9 @@ namespace System.Linq // Do nothing. } - public IPartition<TElement> Skip(int count) - { - return this; - } + public IPartition<TElement> Skip(int count) => this; - public IPartition<TElement> Take(int count) - { - return this; - } + public IPartition<TElement> Take(int count) => this; public TElement TryGetElementAt(int index, out bool found) { @@ -150,20 +140,11 @@ namespace System.Linq return default(TElement); } - public TElement[] ToArray() - { - return Array.Empty<TElement>(); - } + public TElement[] ToArray() => Array.Empty<TElement>(); - public List<TElement> ToList() - { - return new List<TElement>(); - } + public List<TElement> ToList() => new List<TElement>(); - public int GetCount(bool onlyIfCheap) - { - return 0; - } + public int GetCount(bool onlyIfCheap) => 0; } internal sealed class OrderedPartition<TElement> : IPartition<TElement> @@ -245,6 +226,10 @@ namespace System.Linq public static partial class Enumerable { + /// <summary> + /// An iterator that yields the items of part of an <see cref="IList{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source list.</typeparam> private sealed class ListPartition<TSource> : Iterator<TSource>, IPartition<TSource> { private readonly IList<TSource> _source; @@ -390,6 +375,10 @@ namespace System.Linq } } + /// <summary> + /// An iterator that yields the items of part of an <see cref="IEnumerable{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source enumerable.</typeparam> private sealed class EnumerablePartition<TSource> : Iterator<TSource>, IPartition<TSource> { private readonly IEnumerable<TSource> _source; diff --git a/src/System.Linq/src/System/Linq/Range.cs b/src/System.Linq/src/System/Linq/Range.cs index 603e971385..2f5ecbac3a 100644 --- a/src/System.Linq/src/System/Linq/Range.cs +++ b/src/System.Linq/src/System/Linq/Range.cs @@ -25,6 +25,9 @@ namespace System.Linq return new RangeIterator(start, count); } + /// <summary> + /// An iterator that yields a range of consecutive integers. + /// </summary> private sealed class RangeIterator : Iterator<int>, IPartition<int> { private readonly int _start; diff --git a/src/System.Linq/src/System/Linq/Repeat.cs b/src/System.Linq/src/System/Linq/Repeat.cs index e2535f3986..e3fe9c0f72 100644 --- a/src/System.Linq/src/System/Linq/Repeat.cs +++ b/src/System.Linq/src/System/Linq/Repeat.cs @@ -24,6 +24,10 @@ namespace System.Linq return new RepeatIterator<TResult>(element, count); } + /// <summary> + /// An iterator that yields the same item multiple times. + /// </summary> + /// <typeparam name="TResult">The type of the item.</typeparam> private sealed class RepeatIterator<TResult> : Iterator<TResult>, IPartition<TResult> { private readonly int _count; diff --git a/src/System.Linq/src/System/Linq/Reverse.cs b/src/System.Linq/src/System/Linq/Reverse.cs index 81edc65ae0..594eb89a77 100644 --- a/src/System.Linq/src/System/Linq/Reverse.cs +++ b/src/System.Linq/src/System/Linq/Reverse.cs @@ -20,6 +20,10 @@ namespace System.Linq return new ReverseIterator<TSource>(source); } + /// <summary> + /// An iterator that yields the items of an <see cref="IEnumerable{TSource}"/> in reverse. + /// </summary> + /// <typeparam name="TSource">The type of the source enumerable.</typeparam> private sealed class ReverseIterator<TSource> : Iterator<TSource>, IIListProvider<TSource> { private readonly IEnumerable<TSource> _source; diff --git a/src/System.Linq/src/System/Linq/Select.cs b/src/System.Linq/src/System/Linq/Select.cs index 006a0c7688..3e7331982d 100644 --- a/src/System.Linq/src/System/Linq/Select.cs +++ b/src/System.Linq/src/System/Linq/Select.cs @@ -86,6 +86,11 @@ namespace System.Linq } } + /// <summary> + /// An iterator that maps each item of an <see cref="IEnumerable{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source enumerable.</typeparam> + /// <typeparam name="TResult">The type of the mapped items.</typeparam> internal sealed class SelectEnumerableIterator<TSource, TResult> : Iterator<TResult>, IIListProvider<TResult> { private readonly IEnumerable<TSource> _source; @@ -192,6 +197,11 @@ namespace System.Linq } } + /// <summary> + /// An iterator that maps each item of a <see cref="T:TSource[]"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source array.</typeparam> + /// <typeparam name="TResult">The type of the mapped items.</typeparam> internal sealed class SelectArrayIterator<TSource, TResult> : Iterator<TResult>, IPartition<TResult> { private readonly TSource[] _source; @@ -317,6 +327,11 @@ namespace System.Linq } } + /// <summary> + /// An iterator that maps each item of a <see cref="List{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source list.</typeparam> + /// <typeparam name="TResult">The type of the mapped items.</typeparam> internal sealed class SelectListIterator<TSource, TResult> : Iterator<TResult>, IPartition<TResult> { private readonly List<TSource> _source; @@ -459,6 +474,11 @@ namespace System.Linq } } + /// <summary> + /// An iterator that maps each item of an <see cref="IList{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source list.</typeparam> + /// <typeparam name="TResult">The type of the mapped items.</typeparam> internal sealed class SelectIListIterator<TSource, TResult> : Iterator<TResult>, IPartition<TResult> { private readonly IList<TSource> _source; @@ -612,6 +632,11 @@ namespace System.Linq } } + /// <summary> + /// An iterator that maps each item of an <see cref="IPartition{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source partition.</typeparam> + /// <typeparam name="TResult">The type of the mapped items.</typeparam> internal sealed class SelectIPartitionIterator<TSource, TResult> : Iterator<TResult>, IPartition<TResult> { private readonly IPartition<TSource> _source; @@ -787,6 +812,11 @@ namespace System.Linq } } + /// <summary> + /// An iterator that maps each item of part of an <see cref="IList{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source list.</typeparam> + /// <typeparam name="TResult">The type of the mapped items.</typeparam> private sealed class SelectListPartitionIterator<TSource, TResult> : Iterator<TResult>, IPartition<TResult> { private readonly IList<TSource> _source; diff --git a/src/System.Linq/src/System/Linq/Set.cs b/src/System.Linq/src/System/Linq/Set.cs index 60bf491b30..ac0c0afdd5 100644 --- a/src/System.Linq/src/System/Linq/Set.cs +++ b/src/System.Linq/src/System/Linq/Set.cs @@ -7,16 +7,51 @@ using System.Diagnostics; namespace System.Linq { + /// <summary> + /// A lightweight hash set. + /// </summary> + /// <typeparam name="TElement">The type of the set's items.</typeparam> internal sealed class Set<TElement> { + /// <summary> + /// The comparer used to hash and compare items in the set. + /// </summary> private readonly IEqualityComparer<TElement> _comparer; + + /// <summary> + /// The hash buckets, which are used to index into the slots. + /// </summary> private int[] _buckets; + + /// <summary> + /// The slots, each of which store an item and its hash code. + /// </summary> private Slot[] _slots; + + /// <summary> + /// The number of items in this set. + /// </summary> private int _count; + #if DEBUG + /// <summary> + /// Whether <see cref="Remove"/> has been called on this set. + /// </summary> + /// <remarks> + /// When <see cref="Remove"/> runs in debug builds, this flag is set to <c>true</c>. + /// Other methods assert that this flag is <c>false</c> in debug builds, because + /// they make optimizations that may not be correct if <see cref="Remove"/> is called + /// beforehand. + /// </remarks> private bool _haveRemoved; #endif + /// <summary> + /// Constructs a set that compares items with the specified comparer. + /// </summary> + /// <param name="comparer"> + /// The comparer. If this is <c>null</c>, it defaults to <see cref="EqualityComparer{TElement}.Default"/>. + /// </param> public Set(IEqualityComparer<TElement> comparer) { _comparer = comparer ?? EqualityComparer<TElement>.Default; @@ -24,7 +59,13 @@ namespace System.Linq _slots = new Slot[7]; } - // If value is not in set, add it and return true; otherwise return false + /// <summary> + /// Attempts to add an item to this set. + /// </summary> + /// <param name="value">The item to add.</param> + /// <returns> + /// <c>true</c> if the item was not in the set; otherwise, <c>false</c>. + /// </returns> public bool Add(TElement value) { #if DEBUG @@ -54,7 +95,13 @@ namespace System.Linq return true; } - // If value is in set, remove it and return true; otherwise return false + /// <summary> + /// Attempts to remove an item from this set. + /// </summary> + /// <param name="value">The item to remove.</param> + /// <returns> + /// <c>true</c> if the item was in the set; otherwise, <c>false</c>. + /// </returns> public bool Remove(TElement value) { #if DEBUG @@ -86,6 +133,9 @@ namespace System.Linq return false; } + /// <summary> + /// Expands the capacity of this set to double the current capacity, plus one. + /// </summary> private void Resize() { int newSize = checked((_count * 2) + 1); @@ -103,6 +153,10 @@ namespace System.Linq _slots = newSlots; } + /// <summary> + /// Creates an array from the items in this set. + /// </summary> + /// <returns>An array of the items in this set.</returns> internal TElement[] ToArray() { #if DEBUG @@ -117,6 +171,10 @@ namespace System.Linq return array; } + /// <summary> + /// Creates a list from the items in this set. + /// </summary> + /// <returns>A list of the items in this set.</returns> internal List<TElement> ToList() { #if DEBUG @@ -132,21 +190,40 @@ namespace System.Linq return list; } - internal int Count - { - get { return _count; } - } + /// <summary> + /// The number of items in this set. + /// </summary> + internal int Count => _count; + /// <summary> + /// Gets the hash code of the provided value with its sign bit zeroed out, so that modulo has a positive result. + /// </summary> + /// <param name="value">The value to hash.</param> + /// <returns>The lower 31 bits of the value's hash code.</returns> internal int InternalGetHashCode(TElement value) { // Handle comparer implementations that throw when passed null return (value == null) ? 0 : _comparer.GetHashCode(value) & 0x7FFFFFFF; } + /// <summary> + /// An entry in the hash set. + /// </summary> internal struct Slot { + /// <summary> + /// The hash code of the item. + /// </summary> internal int _hashCode; + + /// <summary> + /// In the case of a hash collision, the index of the next slot to probe. + /// </summary> internal int _next; + + /// <summary> + /// The item held by this slot. + /// </summary> internal TElement _value; } } diff --git a/src/System.Linq/src/System/Linq/Union.cs b/src/System.Linq/src/System/Linq/Union.cs index 97c79f701d..431928d3c3 100644 --- a/src/System.Linq/src/System/Linq/Union.cs +++ b/src/System.Linq/src/System/Linq/Union.cs @@ -31,6 +31,10 @@ namespace System.Linq return union != null && AreEqualityComparersEqual(comparer, union._comparer) ? union.Union(second) : new UnionIterator2<TSource>(first, second, comparer); } + /// <summary> + /// An iterator that yields distinct values from two or more <see cref="IEnumerable{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source enumerables.</typeparam> private abstract class UnionIterator<TSource> : Iterator<TSource>, IIListProvider<TSource> { internal readonly IEqualityComparer<TSource> _comparer; @@ -166,7 +170,11 @@ namespace System.Linq return onlyIfCheap ? -1 : FillSet().Count; } } - + + /// <summary> + /// An iterator that yields distinct values from two <see cref="IEnumerable{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source enumerables.</typeparam> private sealed class UnionIterator2<TSource> : UnionIterator<TSource> { private readonly IEnumerable<TSource> _first; @@ -206,6 +214,10 @@ namespace System.Linq } } + /// <summary> + /// An iterator that yields distinct values from three or more <see cref="IEnumerable{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source enumerables.</typeparam> private sealed class UnionIteratorN<TSource> : UnionIterator<TSource> { private readonly UnionIterator<TSource> _previous; diff --git a/src/System.Linq/src/System/Linq/Utilities.cs b/src/System.Linq/src/System/Linq/Utilities.cs index 9dd80d917f..7c226f0a52 100644 --- a/src/System.Linq/src/System/Linq/Utilities.cs +++ b/src/System.Linq/src/System/Linq/Utilities.cs @@ -11,6 +11,13 @@ namespace System.Linq /// </summary> internal static class Utilities { + /// <summary> + /// Decides if two equality comparers are equivalent. + /// </summary> + /// <typeparam name="TSource">The type of each comparer.</typeparam> + /// <param name="left">The first comparer.</param> + /// <param name="right">The second comparer.</param> + /// <returns><c>true</c> if the equality comparers are equal; otherwise, <c>false</c>.</returns> public static bool AreEqualityComparersEqual<TSource>(IEqualityComparer<TSource> left, IEqualityComparer<TSource> right) { if (left == right) @@ -36,11 +43,33 @@ namespace System.Linq return left.Equals(right); } + /// <summary> + /// Combines two predicates. + /// </summary> + /// <typeparam name="TSource">The type of the predicate argument.</typeparam> + /// <param name="predicate1">The first predicate to run.</param> + /// <param name="predicate2">The second predicate to run.</param> + /// <returns> + /// A new predicate that will evaluate to <c>true</c> only if both the first and + /// second predicates return true. If the first predicate returns <c>false</c>, + /// the second predicate will not be run. + /// </returns> public static Func<TSource, bool> CombinePredicates<TSource>(Func<TSource, bool> predicate1, Func<TSource, bool> predicate2) { return x => predicate1(x) && predicate2(x); } + /// <summary> + /// Combines two selectors. + /// </summary> + /// <typeparam name="TSource">The type of the first selector's argument.</typeparam> + /// <typeparam name="TMiddle">The type of the second selector's argument.</typeparam> + /// <typeparam name="TResult">The type of the second selector's return value.</typeparam> + /// <param name="selector1">The first selector to run.</param> + /// <param name="selector2">The second selector to run.</param> + /// <returns> + /// A new selector that represents the composition of the first selector with the second selector. + /// </returns> public static Func<TSource, TResult> CombineSelectors<TSource, TMiddle, TResult>(Func<TSource, TMiddle> selector1, Func<TMiddle, TResult> selector2) { return x => selector2(selector1(x)); diff --git a/src/System.Linq/src/System/Linq/Where.cs b/src/System.Linq/src/System/Linq/Where.cs index 823ab0157b..d2f8e42d5b 100644 --- a/src/System.Linq/src/System/Linq/Where.cs +++ b/src/System.Linq/src/System/Linq/Where.cs @@ -77,6 +77,10 @@ namespace System.Linq } } + /// <summary> + /// An iterator that filters each item of an <see cref="IEnumerable{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source enumerable.</typeparam> internal sealed class WhereEnumerableIterator<TSource> : Iterator<TSource>, IIListProvider<TSource> { private readonly IEnumerable<TSource> _source; @@ -197,6 +201,10 @@ namespace System.Linq } } + /// <summary> + /// An iterator that filters each item of a <see cref="T:TSource[]"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source array.</typeparam> internal sealed class WhereArrayIterator<TSource> : Iterator<TSource>, IIListProvider<TSource> { private readonly TSource[] _source; @@ -299,6 +307,10 @@ namespace System.Linq } } + /// <summary> + /// An iterator that filters each item of a <see cref="List{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source list.</typeparam> internal sealed class WhereListIterator<TSource> : Iterator<TSource>, IIListProvider<TSource> { private readonly List<TSource> _source; @@ -411,6 +423,11 @@ namespace System.Linq } } + /// <summary> + /// An iterator that filters, then maps, each item of a <see cref="T:TSource[]"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source array.</typeparam> + /// <typeparam name="TResult">The type of the mapped items.</typeparam> internal sealed class WhereSelectArrayIterator<TSource, TResult> : Iterator<TResult>, IIListProvider<TResult> { private readonly TSource[] _source; @@ -515,6 +532,11 @@ namespace System.Linq } } + /// <summary> + /// An iterator that filters, then maps, each item of a <see cref="List{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source list.</typeparam> + /// <typeparam name="TResult">The type of the mapped items.</typeparam> internal sealed class WhereSelectListIterator<TSource, TResult> : Iterator<TResult>, IIListProvider<TResult> { private readonly List<TSource> _source; @@ -629,6 +651,11 @@ namespace System.Linq } } + /// <summary> + /// An iterator that filters, then maps, each item of an <see cref="IEnumerable{TSource}"/>. + /// </summary> + /// <typeparam name="TSource">The type of the source enumerable.</typeparam> + /// <typeparam name="TResult">The type of the mapped items.</typeparam> internal sealed class WhereSelectEnumerableIterator<TSource, TResult> : Iterator<TResult>, IIListProvider<TResult> { private readonly IEnumerable<TSource> _source; |