提交 b7ac7a49 编写于 作者: S Stephen Toub 提交者: GitHub

Merge pull request dotnet/corefx#14537 from jamesqo/more-xml-docs

Add XML docs to some Linq iterators

Commit migrated from https://github.com/dotnet/corefx/commit/67414d80dc82f933c9d45beb2d1e9cabac430162
......@@ -41,6 +41,10 @@ public static IEnumerable<TSource> Prepend<TSource>(this IEnumerable<TSource> so
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 @@ public override void Dispose()
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 @@ public override int GetCount(bool onlyIfCheap)
}
}
/// <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 @@ public SingleLinkedNode(TSource first, TSource second)
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 @@ private SingleLinkedNode(SingleLinkedNode<TSource> linked, TSource item)
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 @@ public TSource[] ToArray()
}
}
/// <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;
......
......@@ -6,11 +6,26 @@
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>;
......
......@@ -44,6 +44,10 @@ public static IEnumerable<TSource> Concat<TSource>(this IEnumerable<TSource> fir
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 @@ internal override IEnumerable<TSource> GetEnumerable(int index)
// 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 @@ internal override IEnumerable<TSource> GetEnumerable(int index)
}
}
/// <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 @@ public override TSource[] ToArray()
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 @@ public override TSource[] ToArray()
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;
......
......@@ -24,6 +24,10 @@ public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> s
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;
......
......@@ -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 @@ public IEnumerator<TSource> GetEnumerator()
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()
{
......
......@@ -77,40 +77,36 @@ internal interface IPartition<TElement> : IIListProvider<TElement>
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 @@ void IDisposable.Dispose()
// 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 @@ public TElement TryGetLast(out bool found)
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 @@ public int GetCount(bool onlyIfCheap)
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 @@ public int GetCount(bool onlyIfCheap)
}
}
/// <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;
......
......@@ -25,6 +25,9 @@ public static IEnumerable<int> Range(int start, int count)
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;
......
......@@ -24,6 +24,10 @@ public static IEnumerable<TResult> Repeat<TResult>(TResult element, int count)
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;
......
......@@ -20,6 +20,10 @@ public static IEnumerable<TSource> Reverse<TSource>(this IEnumerable<TSource> so
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;
......
......@@ -86,6 +86,11 @@ public static partial class Enumerable
}
}
/// <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 @@ public int GetCount(bool onlyIfCheap)
}
}
/// <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 @@ public TResult TryGetLast(out bool found)
}
}
/// <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 @@ public TResult TryGetLast(out bool found)
}
}
/// <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 @@ public TResult TryGetLast(out bool found)
}
}
/// <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 @@ public int GetCount(bool onlyIfCheap)
}
}
/// <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;
......
......@@ -7,16 +7,51 @@
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 @@ public Set(IEqualityComparer<TElement> comparer)
_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 @@ public bool Add(TElement value)
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 @@ public bool Remove(TElement value)
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 @@ private void Resize()
_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 @@ internal TElement[] ToArray()
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 @@ internal List<TElement> ToList()
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;
}
}
......
......@@ -31,6 +31,10 @@ public static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> firs
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 @@ public int GetCount(bool onlyIfCheap)
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 @@ internal override UnionIterator<TSource> Union(IEnumerable<TSource> next)
}
}
/// <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;
......
......@@ -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 @@ public static bool AreEqualityComparersEqual<TSource>(IEqualityComparer<TSource>
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));
......
......@@ -77,6 +77,10 @@ private static IEnumerable<TSource> WhereIterator<TSource>(IEnumerable<TSource>
}
}
/// <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 @@ public override IEnumerable<TSource> Where(Func<TSource, bool> predicate)
}
}
/// <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 @@ public override IEnumerable<TSource> Where(Func<TSource, bool> predicate)
}
}
/// <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 @@ public override IEnumerable<TSource> Where(Func<TSource, bool> predicate)
}
}
/// <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 @@ public List<TResult> ToList()
}
}
/// <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 @@ public List<TResult> ToList()
}
}
/// <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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册