Imported Upstream version 4.0.0~alpha1

Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
This commit is contained in:
Jo Shields
2015-04-07 09:35:12 +01:00
parent 283343f570
commit 3c1f479b9d
22469 changed files with 2931443 additions and 869343 deletions

View File

@@ -0,0 +1,128 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// CDSCollectionETWBCLProvider.cs
//
// <OWNER>[....]</OWNER>
//
// A helper class for firing ETW events related to the Coordination Data Structure
// collection types. This provider is used by CDS collections in both mscorlib.dll
// and System.dll. The purpose of sharing the provider class is to be able to enable
// ETW tracing on all CDS collection with a single ETW provider GUID, and to minimize
// the number of providers in use.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
using System;
using System.Collections.Generic;
using System.Text;
namespace System.Collections.Concurrent
{
#if !FEATURE_PAL // PAL doesn't support eventing
using System.Diagnostics.Tracing;
/// <summary>Provides an event source for tracing CDS collection information.</summary>
[System.Runtime.CompilerServices.FriendAccessAllowed]
[EventSource(
Name = "System.Collections.Concurrent.ConcurrentCollectionsEventSource",
Guid = "35167F8E-49B2-4b96-AB86-435B59336B5E",
LocalizationResources = "mscorlib")]
internal sealed class CDSCollectionETWBCLProvider : EventSource
{
/// <summary>
/// Defines the singleton instance for the collection ETW provider.
/// The collection provider GUID is {35167F8E-49B2-4b96-AB86-435B59336B5E}.
/// </summary>
public static CDSCollectionETWBCLProvider Log = new CDSCollectionETWBCLProvider();
/// <summary>Prevent external instantiation. All logging should go through the Log instance.</summary>
private CDSCollectionETWBCLProvider() { }
/// <summary>Enabled for all keywords.</summary>
private const EventKeywords ALL_KEYWORDS = (EventKeywords)(-1);
//-----------------------------------------------------------------------------------
//
// CDS Collection Event IDs (must be unique)
//
private const int CONCURRENTSTACK_FASTPUSHFAILED_ID = 1;
private const int CONCURRENTSTACK_FASTPOPFAILED_ID = 2;
private const int CONCURRENTDICTIONARY_ACQUIRINGALLLOCKS_ID = 3;
private const int CONCURRENTBAG_TRYTAKESTEALS_ID = 4;
private const int CONCURRENTBAG_TRYPEEKSTEALS_ID = 5;
/////////////////////////////////////////////////////////////////////////////////////
//
// ConcurrentStack Events
//
[Event(CONCURRENTSTACK_FASTPUSHFAILED_ID, Level = EventLevel.Warning)]
public void ConcurrentStack_FastPushFailed(int spinCount)
{
if (IsEnabled(EventLevel.Warning, ALL_KEYWORDS))
{
WriteEvent(CONCURRENTSTACK_FASTPUSHFAILED_ID, spinCount);
}
}
[Event(CONCURRENTSTACK_FASTPOPFAILED_ID, Level = EventLevel.Warning)]
public void ConcurrentStack_FastPopFailed(int spinCount)
{
if (IsEnabled(EventLevel.Warning, ALL_KEYWORDS))
{
WriteEvent(CONCURRENTSTACK_FASTPOPFAILED_ID, spinCount);
}
}
/////////////////////////////////////////////////////////////////////////////////////
//
// ConcurrentDictionary Events
//
[Event(CONCURRENTDICTIONARY_ACQUIRINGALLLOCKS_ID, Level = EventLevel.Warning)]
public void ConcurrentDictionary_AcquiringAllLocks(int numOfBuckets)
{
if (IsEnabled(EventLevel.Warning, ALL_KEYWORDS))
{
WriteEvent(CONCURRENTDICTIONARY_ACQUIRINGALLLOCKS_ID, numOfBuckets);
}
}
//
// Events below this point are used by the CDS types in System.DLL
//
/////////////////////////////////////////////////////////////////////////////////////
//
// ConcurrentBag Events
//
[Event(CONCURRENTBAG_TRYTAKESTEALS_ID, Level = EventLevel.Verbose)]
public void ConcurrentBag_TryTakeSteals()
{
if (IsEnabled(EventLevel.Verbose, ALL_KEYWORDS))
{
WriteEvent(CONCURRENTBAG_TRYTAKESTEALS_ID);
}
}
[Event(CONCURRENTBAG_TRYPEEKSTEALS_ID, Level = EventLevel.Verbose)]
public void ConcurrentBag_TryPeekSteals()
{
if (IsEnabled(EventLevel.Verbose, ALL_KEYWORDS))
{
WriteEvent(CONCURRENTBAG_TRYPEEKSTEALS_ID);
}
}
}
#endif // !FEATURE_PAL
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,119 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// IProducerConsumerCollection.cs
//
// <OWNER>[....]</OWNER>
//
// A common interface for all concurrent collections.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
namespace System.Collections.Concurrent
{
/// <summary>
/// Defines methods to manipulate thread-safe collections intended for producer/consumer usage.
/// </summary>
/// <typeparam name="T">Specifies the type of elements in the collection.</typeparam>
/// <remarks>
/// All implementations of this interface must enable all members of this interface
/// to be used concurrently from multiple threads.
/// </remarks>
public interface IProducerConsumerCollection<T> : IEnumerable<T>, ICollection
{
/// <summary>
/// Copies the elements of the <see cref="IProducerConsumerCollection{T}"/> to
/// an
/// <see cref="T:System.Array"/>, starting at a specified index.
/// </summary>
/// <param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of
/// the elements copied from the <see cref="IProducerConsumerCollection{T}"/>.
/// The array must have zero-based indexing.</param>
/// <param name="index">The zero-based index in <paramref name="array"/> at which copying
/// begins.</param>
/// <exception cref="ArgumentNullException"><paramref name="array"/> is a null reference (Nothing in
/// Visual Basic).</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than
/// zero.</exception>
/// <exception cref="ArgumentException"><paramref name="index"/> is equal to or greater than the
/// length of the <paramref name="array"/>
/// -or- The number of elements in the source <see cref="ConcurrentQueue{T}"/> is greater than the
/// available space from <paramref name="index"/> to the end of the destination <paramref
/// name="array"/>.
/// </exception>
void CopyTo(T[] array, int index);
/// <summary>
/// Attempts to add an object to the <see
/// cref="IProducerConsumerCollection{T}"/>.
/// </summary>
/// <param name="item">The object to add to the <see
/// cref="IProducerConsumerCollection{T}"/>.</param>
/// <returns>true if the object was added successfully; otherwise, false.</returns>
/// <exception cref="T:System.ArgumentException">The <paramref name="item"/> was invalid for this collection.</exception>
bool TryAdd(T item);
/// <summary>
/// Attempts to remove and return an object from the <see cref="IProducerConsumerCollection{T}"/>.
/// </summary>
/// <param name="item">
/// When this method returns, if the object was removed and returned successfully, <paramref
/// name="item"/> contains the removed object. If no object was available to be removed, the value is
/// unspecified.
/// </param>
/// <returns>true if an object was removed and returned successfully; otherwise, false.</returns>
bool TryTake(out T item);
/// <summary>
/// Copies the elements contained in the <see cref="IProducerConsumerCollection{T}"/> to a new array.
/// </summary>
/// <returns>A new array containing the elements copied from the <see cref="IProducerConsumerCollection{T}"/>.</returns>
T[] ToArray();
}
/// <summary>
/// A debugger view of the IProducerConsumerCollection that makes it simple to browse the
/// collection's contents at a point in time.
/// </summary>
/// <typeparam name="T">The type of elements stored within.</typeparam>
internal sealed class SystemCollectionsConcurrent_ProducerConsumerCollectionDebugView<T>
{
private IProducerConsumerCollection<T> m_collection; // The collection being viewed.
/// <summary>
/// Constructs a new debugger view object for the provided collection object.
/// </summary>
/// <param name="collection">A collection to browse in the debugger.</param>
public SystemCollectionsConcurrent_ProducerConsumerCollectionDebugView(IProducerConsumerCollection<T> collection)
{
if (collection == null)
{
throw new ArgumentNullException("collection");
}
m_collection = collection;
}
/// <summary>
/// Returns a snapshot of the underlying collection's elements.
/// </summary>
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public T[] Items
{
get { return m_collection.ToArray(); }
}
}
}

View File

@@ -0,0 +1,284 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// OrderablePartitioner.cs
//
// <OWNER>[....]</OWNER>
//
//
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
using System;
using System.Collections.Generic;
using System.Security.Permissions;
using System.Threading;
namespace System.Collections.Concurrent
{
/// <summary>
/// Represents a particular manner of splitting an orderable data source into multiple partitions.
/// </summary>
/// <typeparam name="TSource">Type of the elements in the collection.</typeparam>
/// <remarks>
/// <para>
/// Each element in each partition has an integer index associated with it, which determines the relative
/// order of that element against elements in other partitions.
/// </para>
/// <para>
/// Inheritors of <see cref="OrderablePartitioner{TSource}"/> must adhere to the following rules:
/// <ol>
/// <li>All indices must be unique, such that there may not be duplicate indices. If all indices are not
/// unique, the output ordering may be scrambled.</li>
/// <li>All indices must be non-negative. If any indices are negative, consumers of the implementation
/// may throw exceptions.</li>
/// <li><see cref="GetPartitions"/> and <see cref="GetOrderablePartitions"/> should throw a
/// <see cref="T:System.ArgumentOutOfRangeException"/> if the requested partition count is less than or
/// equal to zero.</li>
/// <li><see cref="GetPartitions"/> and <see cref="GetOrderablePartitions"/> should always return a number
/// of enumerables equal to the requested partition count. If the partitioner runs out of data and cannot
/// create as many partitions as requested, an empty enumerator should be returned for each of the
/// remaining partitions. If this rule is not followed, consumers of the implementation may throw a <see
/// cref="T:System.InvalidOperationException"/>.</li>
/// <li><see cref="GetPartitions"/>, <see cref="GetOrderablePartitions"/>,
/// <see cref="GetDynamicPartitions"/>, and <see cref="GetOrderableDynamicPartitions"/>
/// should never return null. If null is returned, a consumer of the implementation may throw a
/// <see cref="T:System.InvalidOperationException"/>.</li>
/// <li><see cref="GetPartitions"/>, <see cref="GetOrderablePartitions"/>,
/// <see cref="GetDynamicPartitions"/>, and <see cref="GetOrderableDynamicPartitions"/>
/// should always return partitions that can fully and uniquely enumerate the input data source. All of
/// the data and only the data contained in the input source should be enumerated, with no duplication
/// that was not already in the input, unless specifically required by the particular partitioner's
/// design. If this is not followed, the output ordering may be scrambled.</li>
/// <li>If <see cref="KeysOrderedInEachPartition"/> returns true, each partition must return elements
/// with increasing key indices.</li>
/// <li>If <see cref="KeysOrderedAcrossPartitions"/> returns true, all the keys in partition numbered N
/// must be larger than all the keys in partition numbered N-1.</li>
/// <li>If <see cref="KeysNormalized"/> returns true, all indices must be monotonically increasing from
/// 0, though not necessarily within a single partition.</li>
/// </ol>
/// </para>
/// </remarks>
[HostProtection(Synchronization = true, ExternalThreading = true)]
public abstract class OrderablePartitioner<TSource> : Partitioner<TSource>
{
/// <summary>
/// Initializes a new instance of the <see cref="OrderablePartitioner{TSource}"/> class with the
/// specified constraints on the index keys.
/// </summary>
/// <param name="keysOrderedInEachPartition">
/// Indicates whether the elements in each partition are yielded in the order of
/// increasing keys.
/// </param>
/// <param name="keysOrderedAcrossPartitions">
/// Indicates whether elements in an earlier partition always come before
/// elements in a later partition. If true, each element in partition 0 has a smaller order key than
/// any element in partition 1, each element in partition 1 has a smaller order key than any element
/// in partition 2, and so on.
/// </param>
/// <param name="keysNormalized">
/// Indicates whether keys are normalized. If true, all order keys are distinct
/// integers in the range [0 .. numberOfElements-1]. If false, order keys must still be dictinct, but
/// only their relative order is considered, not their absolute values.
/// </param>
protected OrderablePartitioner(bool keysOrderedInEachPartition, bool keysOrderedAcrossPartitions, bool keysNormalized)
{
KeysOrderedInEachPartition = keysOrderedInEachPartition;
KeysOrderedAcrossPartitions = keysOrderedAcrossPartitions;
KeysNormalized = keysNormalized;
}
/// <summary>
/// Partitions the underlying collection into the specified number of orderable partitions.
/// </summary>
/// <remarks>
/// Each partition is represented as an enumerator over key-value pairs.
/// The value of the pair is the element itself, and the key is an integer which determines
/// the relative ordering of this element against other elements in the data source.
/// </remarks>
/// <param name="partitionCount">The number of partitions to create.</param>
/// <returns>A list containing <paramref name="partitionCount"/> enumerators.</returns>
public abstract IList<IEnumerator<KeyValuePair<long, TSource>>> GetOrderablePartitions(int partitionCount);
/// <summary>
/// Creates an object that can partition the underlying collection into a variable number of
/// partitions.
/// </summary>
/// <remarks>
/// <para>
/// The returned object implements the <see
/// cref="T:System.Collections.Generic.IEnumerable{TSource}"/> interface. Calling <see
/// cref="System.Collections.Generic.IEnumerable{TSource}.GetEnumerator">GetEnumerator</see> on the
/// object creates another partition over the sequence.
/// </para>
/// <para>
/// Each partition is represented as an enumerator over key-value pairs. The value in the pair is the element
/// itself, and the key is an integer which determines the relative ordering of this element against
/// other elements.
/// </para>
/// <para>
/// The <see cref="GetOrderableDynamicPartitions"/> method is only supported if the <see
/// cref="System.Collections.Concurrent.Partitioner{TSource}.SupportsDynamicPartitions">SupportsDynamicPartitions</see>
/// property returns true.
/// </para>
/// </remarks>
/// <returns>An object that can create partitions over the underlying data source.</returns>
/// <exception cref="NotSupportedException">Dynamic partitioning is not supported by this
/// partitioner.</exception>
public virtual IEnumerable<KeyValuePair<long, TSource>> GetOrderableDynamicPartitions()
{
throw new NotSupportedException(Environment.GetResourceString("Partitioner_DynamicPartitionsNotSupported"));
}
/// <summary>
/// Gets whether elements in each partition are yielded in the order of increasing keys.
/// </summary>
public bool KeysOrderedInEachPartition { get; private set; }
/// <summary>
/// Gets whether elements in an earlier partition always come before elements in a later partition.
/// </summary>
/// <remarks>
/// If <see cref="KeysOrderedAcrossPartitions"/> returns true, each element in partition 0 has a
/// smaller order key than any element in partition 1, each element in partition 1 has a smaller
/// order key than any element in partition 2, and so on.
/// </remarks>
public bool KeysOrderedAcrossPartitions { get; private set; }
/// <summary>
/// Gets whether order keys are normalized.
/// </summary>
/// <remarks>
/// If <see cref="KeysNormalized"/> returns true, all order keys are distinct integers in the range
/// [0 .. numberOfElements-1]. If the property returns false, order keys must still be dictinct, but
/// only their relative order is considered, not their absolute values.
/// </remarks>
public bool KeysNormalized { get; private set; }
/// <summary>
/// Partitions the underlying collection into the given number of ordered partitions.
/// </summary>
/// <remarks>
/// The default implementation provides the same behavior as <see cref="GetOrderablePartitions"/> except
/// that the returned set of partitions does not provide the keys for the elements.
/// </remarks>
/// <param name="partitionCount">The number of partitions to create.</param>
/// <returns>A list containing <paramref name="partitionCount"/> enumerators.</returns>
public override IList<IEnumerator<TSource>> GetPartitions(int partitionCount)
{
IList<IEnumerator<KeyValuePair<long, TSource>>> orderablePartitions = GetOrderablePartitions(partitionCount);
if (orderablePartitions.Count != partitionCount)
{
throw new InvalidOperationException("OrderablePartitioner_GetPartitions_WrongNumberOfPartitions");
}
IEnumerator<TSource>[] partitions = new IEnumerator<TSource>[partitionCount];
for (int i = 0; i < partitionCount; i++)
{
partitions[i] = new EnumeratorDropIndices(orderablePartitions[i]);
}
return partitions;
}
/// <summary>
/// Creates an object that can partition the underlying collection into a variable number of
/// partitions.
/// </summary>
/// <remarks>
/// <para>
/// The returned object implements the <see
/// cref="T:System.Collections.Generic.IEnumerable{TSource}"/> interface. Calling <see
/// cref="System.Collections.Generic.IEnumerable{TSource}.GetEnumerator">GetEnumerator</see> on the
/// object creates another partition over the sequence.
/// </para>
/// <para>
/// The default implementation provides the same behavior as <see cref="GetOrderableDynamicPartitions"/> except
/// that the returned set of partitions does not provide the keys for the elements.
/// </para>
/// <para>
/// The <see cref="GetDynamicPartitions"/> method is only supported if the <see
/// cref="System.Collections.Concurrent.Partitioner{TSource}.SupportsDynamicPartitions"/>
/// property returns true.
/// </para>
/// </remarks>
/// <returns>An object that can create partitions over the underlying data source.</returns>
/// <exception cref="NotSupportedException">Dynamic partitioning is not supported by this
/// partitioner.</exception>
public override IEnumerable<TSource> GetDynamicPartitions()
{
IEnumerable<KeyValuePair<long, TSource>> orderablePartitions = GetOrderableDynamicPartitions();
return new EnumerableDropIndices(orderablePartitions);
}
/// <summary>
/// Converts an enumerable over key-value pairs to an enumerable over values.
/// </summary>
private class EnumerableDropIndices : IEnumerable<TSource>, IDisposable
{
private readonly IEnumerable<KeyValuePair<long, TSource>> m_source;
public EnumerableDropIndices(IEnumerable<KeyValuePair<long, TSource>> source)
{
m_source = source;
}
public IEnumerator<TSource> GetEnumerator()
{
return new EnumeratorDropIndices(m_source.GetEnumerator());
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((EnumerableDropIndices)this).GetEnumerator();
}
public void Dispose()
{
IDisposable d = m_source as IDisposable;
if (d != null)
{
d.Dispose();
}
}
}
private class EnumeratorDropIndices : IEnumerator<TSource>
{
private readonly IEnumerator<KeyValuePair<long, TSource>> m_source;
public EnumeratorDropIndices(IEnumerator<KeyValuePair<long, TSource>> source)
{
m_source = source;
}
public bool MoveNext()
{
return m_source.MoveNext();
}
public TSource Current
{
get
{
return m_source.Current.Value;
}
}
Object IEnumerator.Current
{
get
{
return ((EnumeratorDropIndices)this).Current;
}
}
public void Dispose()
{
m_source.Dispose();
}
public void Reset()
{
m_source.Reset();
}
}
}
}

View File

@@ -0,0 +1,105 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// Partitioner.cs
//
// <OWNER>[....]</OWNER>
//
// Represents a particular way of splitting a collection into multiple partitions.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
using System;
using System.Collections.Generic;
using System.Security.Permissions;
using System.Threading;
namespace System.Collections.Concurrent
{
/// <summary>
/// Represents a particular manner of splitting a data source into multiple partitions.
/// </summary>
/// <typeparam name="TSource">Type of the elements in the collection.</typeparam>
/// <remarks>
/// <para>
/// Inheritors of <see cref="Partitioner{TSource}"/> must adhere to the following rules:
/// <ol>
/// <li><see cref="GetPartitions"/> should throw a
/// <see cref="T:System.ArgumentOutOfRangeException"/> if the requested partition count is less than or
/// equal to zero.</li>
/// <li><see cref="GetPartitions"/> should always return a number of enumerables equal to the requested
/// partition count. If the partitioner runs out of data and cannot create as many partitions as
/// requested, an empty enumerator should be returned for each of the remaining partitions. If this rule
/// is not followed, consumers of the implementation may throw a <see
/// cref="T:System.InvalidOperationException"/>.</li>
/// <li><see cref="GetPartitions"/> and <see cref="GetDynamicPartitions"/>
/// should never return null. If null is returned, a consumer of the implementation may throw a
/// <see cref="T:System.InvalidOperationException"/>.</li>
/// <li><see cref="GetPartitions"/> and <see cref="GetDynamicPartitions"/> should always return
/// partitions that can fully and uniquely enumerate the input data source. All of the data and only the
/// data contained in the input source should be enumerated, with no duplication that was not already in
/// the input, unless specifically required by the particular partitioner's design. If this is not
/// followed, the output ordering may be scrambled.</li>
/// </ol>
/// </para>
/// </remarks>
[HostProtection(Synchronization = true, ExternalThreading = true)]
public abstract class Partitioner<TSource>
{
/// <summary>
/// Partitions the underlying collection into the given number of partitions.
/// </summary>
/// <param name="partitionCount">The number of partitions to create.</param>
/// <returns>A list containing <paramref name="partitionCount"/> enumerators.</returns>
public abstract IList<IEnumerator<TSource>> GetPartitions(int partitionCount);
/// <summary>
/// Gets whether additional partitions can be created dynamically.
/// </summary>
/// <returns>
/// true if the <see cref="Partitioner{TSource}"/> can create partitions dynamically as they are
/// requested; false if the <see cref="Partitioner{TSource}"/> can only allocate
/// partitions statically.
/// </returns>
/// <remarks>
/// <para>
/// If a derived class does not override and implement <see cref="GetDynamicPartitions"/>,
/// <see cref="SupportsDynamicPartitions"/> should return false. The value of <see
/// cref="SupportsDynamicPartitions"/> should not vary over the lifetime of this instance.
/// </para>
/// </remarks>
public virtual bool SupportsDynamicPartitions
{
get { return false; }
}
/// <summary>
/// Creates an object that can partition the underlying collection into a variable number of
/// partitions.
/// </summary>
/// <remarks>
/// <para>
/// The returned object implements the <see
/// cref="T:System.Collections.Generic.IEnumerable{TSource}"/> interface. Calling <see
/// cref="System.Collections.Generic.IEnumerable{TSource}.GetEnumerator">GetEnumerator</see> on the
/// object creates another partition over the sequence.
/// </para>
/// <para>
/// The <see cref="GetDynamicPartitions"/> method is only supported if the <see
/// cref="SupportsDynamicPartitions"/>
/// property returns true.
/// </para>
/// </remarks>
/// <returns>An object that can create partitions over the underlying data source.</returns>
/// <exception cref="NotSupportedException">Dynamic partitioning is not supported by this
/// partitioner.</exception>
public virtual IEnumerable<TSource> GetDynamicPartitions()
{
throw new NotSupportedException(Environment.GetResourceString("Partitioner_DynamicPartitionsNotSupported"));
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
bf7ec8f88e3e31969c5db3673e784dcfb80c8aa0

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,80 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: CaseInsensitiveComparer
**
** <OWNER>[....]</OWNER>
**
**
**
============================================================*/
namespace System.Collections {
//This class does not contain members and does not need to be serializable
using System;
using System.Collections;
using System.Globalization;
using System.Diagnostics.Contracts;
[Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public class CaseInsensitiveComparer : IComparer {
private CompareInfo m_compareInfo;
private static volatile CaseInsensitiveComparer m_InvariantCaseInsensitiveComparer;
public CaseInsensitiveComparer() {
m_compareInfo = CultureInfo.CurrentCulture.CompareInfo;
}
public CaseInsensitiveComparer(CultureInfo culture) {
if (culture==null) {
throw new ArgumentNullException("culture");
}
Contract.EndContractBlock();
m_compareInfo = culture.CompareInfo;
}
public static CaseInsensitiveComparer Default
{
get
{
Contract.Ensures(Contract.Result<CaseInsensitiveComparer>() != null);
return new CaseInsensitiveComparer(CultureInfo.CurrentCulture);
}
}
public static CaseInsensitiveComparer DefaultInvariant
{
get
{
Contract.Ensures(Contract.Result<CaseInsensitiveComparer>() != null);
if (m_InvariantCaseInsensitiveComparer == null) {
m_InvariantCaseInsensitiveComparer = new CaseInsensitiveComparer(CultureInfo.InvariantCulture);
}
return m_InvariantCaseInsensitiveComparer;
}
}
// Behaves exactly like Comparer.Default.Compare except that the comparison is case insensitive
// Compares two Objects by calling CompareTo. If a ==
// b,0 is returned. If a implements
// IComparable, a.CompareTo(b) is returned. If a
// doesn't implement IComparable and b does,
// -(b.CompareTo(a)) is returned, otherwise an
// exception is thrown.
//
public int Compare(Object a, Object b) {
String sa = a as String;
String sb = b as String;
if (sa != null && sb != null)
return m_compareInfo.Compare(sa, sb, CompareOptions.IgnoreCase);
else
return Comparer.Default.Compare(a,b);
}
}
}

View File

@@ -0,0 +1,83 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: CaseInsensitiveHashCodeProvider
**
** <OWNER>[....]</OWNER>
**
**
** Purpose: Designed to support hashtables which require
** case-insensitive behavior while still maintaining case,
** this provides an efficient mechanism for getting the
** hashcode of the string ignoring case.
**
**
============================================================*/
namespace System.Collections {
//This class does not contain members and does not need to be serializable
using System;
using System.Collections;
using System.Globalization;
using System.Diagnostics.Contracts;
[Serializable]
[Obsolete("Please use StringComparer instead.")]
[System.Runtime.InteropServices.ComVisible(true)]
public class CaseInsensitiveHashCodeProvider : IHashCodeProvider {
private TextInfo m_text;
private static volatile CaseInsensitiveHashCodeProvider m_InvariantCaseInsensitiveHashCodeProvider = null;
public CaseInsensitiveHashCodeProvider() {
m_text = CultureInfo.CurrentCulture.TextInfo;
}
public CaseInsensitiveHashCodeProvider(CultureInfo culture) {
if (culture==null) {
throw new ArgumentNullException("culture");
}
Contract.EndContractBlock();
m_text = culture.TextInfo;
}
public static CaseInsensitiveHashCodeProvider Default
{
get
{
Contract.Ensures(Contract.Result<CaseInsensitiveHashCodeProvider>() != null);
return new CaseInsensitiveHashCodeProvider(CultureInfo.CurrentCulture);
}
}
public static CaseInsensitiveHashCodeProvider DefaultInvariant
{
get
{
Contract.Ensures(Contract.Result<CaseInsensitiveHashCodeProvider>() != null);
if (m_InvariantCaseInsensitiveHashCodeProvider == null) {
m_InvariantCaseInsensitiveHashCodeProvider = new CaseInsensitiveHashCodeProvider(CultureInfo.InvariantCulture);
}
return m_InvariantCaseInsensitiveHashCodeProvider;
}
}
public int GetHashCode(Object obj) {
if (obj==null) {
throw new ArgumentNullException("obj");
}
Contract.EndContractBlock();
String s = obj as String;
if (s==null) {
return obj.GetHashCode();
}
return m_text.GetCaseInsensitiveHashCode(s);
}
}
}

View File

@@ -0,0 +1,217 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// <OWNER>[....]</OWNER>
//
namespace System.Collections {
using System;
using System.Diagnostics.Contracts;
// Useful base class for typed read/write collections where items derive from object
[Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public abstract class CollectionBase : IList {
ArrayList list;
protected CollectionBase() {
list = new ArrayList();
}
protected CollectionBase(int capacity) {
list = new ArrayList(capacity);
}
protected ArrayList InnerList {
get {
if (list == null)
list = new ArrayList();
return list;
}
}
protected IList List {
get { return (IList)this; }
}
[System.Runtime.InteropServices.ComVisible(false)]
public int Capacity {
get {
return InnerList.Capacity;
}
set {
InnerList.Capacity = value;
}
}
public int Count {
get {
return list == null ? 0 : list.Count;
}
}
public void Clear() {
OnClear();
InnerList.Clear();
OnClearComplete();
}
public void RemoveAt(int index) {
if (index < 0 || index >= Count)
throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
Contract.EndContractBlock();
Object temp = InnerList[index];
OnValidate(temp);
OnRemove(index, temp);
InnerList.RemoveAt(index);
try {
OnRemoveComplete(index, temp);
}
catch {
InnerList.Insert(index, temp);
throw;
}
}
bool IList.IsReadOnly {
get { return InnerList.IsReadOnly; }
}
bool IList.IsFixedSize {
get { return InnerList.IsFixedSize; }
}
bool ICollection.IsSynchronized {
get { return InnerList.IsSynchronized; }
}
Object ICollection.SyncRoot {
get { return InnerList.SyncRoot; }
}
void ICollection.CopyTo(Array array, int index) {
InnerList.CopyTo(array, index);
}
Object IList.this[int index] {
get {
if (index < 0 || index >= Count)
throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
Contract.EndContractBlock();
return InnerList[index];
}
set {
if (index < 0 || index >= Count)
throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
Contract.EndContractBlock();
OnValidate(value);
Object temp = InnerList[index];
OnSet(index, temp, value);
InnerList[index] = value;
try {
OnSetComplete(index, temp, value);
}
catch {
InnerList[index] = temp;
throw;
}
}
}
bool IList.Contains(Object value) {
return InnerList.Contains(value);
}
int IList.Add(Object value) {
OnValidate(value);
OnInsert(InnerList.Count, value);
int index = InnerList.Add(value);
try {
OnInsertComplete(index, value);
}
catch {
InnerList.RemoveAt(index);
throw;
}
return index;
}
void IList.Remove(Object value) {
OnValidate(value);
int index = InnerList.IndexOf(value);
if (index < 0) throw new ArgumentException(Environment.GetResourceString("Arg_RemoveArgNotFound"));
OnRemove(index, value);
InnerList.RemoveAt(index);
try{
OnRemoveComplete(index, value);
}
catch {
InnerList.Insert(index, value);
throw;
}
}
int IList.IndexOf(Object value) {
return InnerList.IndexOf(value);
}
void IList.Insert(int index, Object value) {
if (index < 0 || index > Count)
throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
Contract.EndContractBlock();
OnValidate(value);
OnInsert(index, value);
InnerList.Insert(index, value);
try {
OnInsertComplete(index, value);
}
catch {
InnerList.RemoveAt(index);
throw;
}
}
public IEnumerator GetEnumerator() {
return InnerList.GetEnumerator();
}
protected virtual void OnSet(int index, Object oldValue, Object newValue) {
}
protected virtual void OnInsert(int index, Object value) {
}
protected virtual void OnClear() {
}
protected virtual void OnRemove(int index, Object value) {
}
protected virtual void OnValidate(Object value) {
if (value == null) throw new ArgumentNullException("value");
Contract.EndContractBlock();
}
protected virtual void OnSetComplete(int index, Object oldValue, Object newValue) {
}
protected virtual void OnInsertComplete(int index, Object value) {
}
protected virtual void OnClearComplete() {
}
protected virtual void OnRemoveComplete(int index, Object value) {
}
}
}

View File

@@ -0,0 +1,100 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: Comparer
**
** <OWNER>[....]</OWNER>
**
**
** Purpose: Default IComparer implementation.
**
**
===========================================================*/
namespace System.Collections {
using System;
using System.Globalization;
using System.Runtime.Serialization;
using System.Security.Permissions;
using System.Diagnostics.Contracts;
[Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class Comparer : IComparer , ISerializable
{
private CompareInfo m_compareInfo;
public static readonly Comparer Default = new Comparer(CultureInfo.CurrentCulture);
public static readonly Comparer DefaultInvariant = new Comparer(CultureInfo.InvariantCulture);
private const String CompareInfoName = "CompareInfo";
private Comparer() {
m_compareInfo = null;
}
public Comparer(CultureInfo culture) {
if (culture==null) {
throw new ArgumentNullException("culture");
}
Contract.EndContractBlock();
m_compareInfo = culture.CompareInfo;
}
private Comparer(SerializationInfo info, StreamingContext context) {
m_compareInfo = null;
SerializationInfoEnumerator enumerator = info.GetEnumerator();
while( enumerator.MoveNext()) {
switch( enumerator.Name) {
case CompareInfoName:
m_compareInfo = (CompareInfo) info.GetValue(CompareInfoName, typeof(CompareInfo));
break;
}
}
}
// Compares two Objects by calling CompareTo. If a ==
// b,0 is returned. If a implements
// IComparable, a.CompareTo(b) is returned. If a
// doesn't implement IComparable and b does,
// -(b.CompareTo(a)) is returned, otherwise an
// exception is thrown.
//
public int Compare(Object a, Object b) {
if (a == b) return 0;
if (a == null) return -1;
if (b == null) return 1;
if (m_compareInfo != null) {
String sa = a as String;
String sb = b as String;
if (sa != null && sb != null)
return m_compareInfo.Compare(sa, sb);
}
IComparable ia = a as IComparable;
if (ia != null)
return ia.CompareTo(b);
IComparable ib = b as IComparable;
if (ib != null)
return -ib.CompareTo(a);
throw new ArgumentException(Environment.GetResourceString("Argument_ImplementIComparable"));
}
[System.Security.SecurityCritical] // auto-generated_required
public void GetObjectData(SerializationInfo info, StreamingContext context) {
if (info==null) {
throw new ArgumentNullException("info");
}
Contract.EndContractBlock();
if( m_compareInfo != null) {
info.AddValue(CompareInfoName, m_compareInfo);
}
}
}
}

View File

@@ -0,0 +1,69 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// <OWNER>[....]</OWNER>
//
using System.Diagnostics.Contracts;
namespace System.Collections {
[Serializable]
internal class CompatibleComparer: IEqualityComparer {
IComparer _comparer;
#pragma warning disable 618
IHashCodeProvider _hcp;
internal CompatibleComparer(IComparer comparer, IHashCodeProvider hashCodeProvider) {
_comparer = comparer;
_hcp = hashCodeProvider;
}
#pragma warning restore 618
public int Compare(Object a, Object b) {
if (a == b) return 0;
if (a == null) return -1;
if (b == null) return 1;
if (_comparer != null)
return _comparer.Compare(a,b);
IComparable ia = a as IComparable;
if (ia != null)
return ia.CompareTo(b);
throw new ArgumentException(Environment.GetResourceString("Argument_ImplementIComparable"));
}
public new bool Equals(Object a, Object b) {
return Compare(a, b) == 0;
}
public int GetHashCode(Object obj) {
if( obj == null) {
throw new ArgumentNullException("obj");
}
Contract.EndContractBlock();
if (_hcp != null)
return _hcp.GetHashCode(obj);
return obj.GetHashCode();
}
// These are helpers for the Hashtable to query the IKeyComparer infrastructure.
internal IComparer Comparer {
get {
return _comparer;
}
}
// These are helpers for the Hashtable to query the IKeyComparer infrastructure.
#pragma warning disable 618
internal IHashCodeProvider HashCodeProvider {
get {
return _hcp;
}
}
#pragma warning restore 618
}
}

View File

@@ -0,0 +1,183 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// <OWNER>[....]</OWNER>
//
namespace System.Collections {
using System;
using System.Security.Permissions;
// Useful base class for typed read/write collections where items derive from object
[Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public abstract class DictionaryBase : IDictionary {
Hashtable hashtable;
protected Hashtable InnerHashtable {
get {
if (hashtable == null)
hashtable = new Hashtable();
return hashtable;
}
}
protected IDictionary Dictionary {
get { return (IDictionary) this; }
}
public int Count {
// to avoid newing inner list if no items are ever added
get { return hashtable == null ? 0 : hashtable.Count; }
}
bool IDictionary.IsReadOnly {
get { return InnerHashtable.IsReadOnly; }
}
bool IDictionary.IsFixedSize {
get { return InnerHashtable.IsFixedSize; }
}
bool ICollection.IsSynchronized {
get { return InnerHashtable.IsSynchronized; }
}
ICollection IDictionary.Keys {
get {
return InnerHashtable.Keys;
}
}
Object ICollection.SyncRoot {
get { return InnerHashtable.SyncRoot; }
}
ICollection IDictionary.Values {
get {
return InnerHashtable.Values;
}
}
public void CopyTo(Array array, int index) {
InnerHashtable.CopyTo(array, index);
}
object IDictionary.this[object key] {
get {
object currentValue = InnerHashtable[key];
OnGet(key, currentValue);
return currentValue;
}
set {
OnValidate(key, value);
bool keyExists = true;
Object temp = InnerHashtable[key];
if( temp == null) {
keyExists = InnerHashtable.Contains(key);
}
OnSet(key, temp, value);
InnerHashtable[key] = value;
try {
OnSetComplete(key, temp, value);
}
catch {
if( keyExists) {
InnerHashtable[key] = temp;
}
else {
InnerHashtable.Remove(key);
}
throw;
}
}
}
bool IDictionary.Contains(object key) {
return InnerHashtable.Contains(key);
}
void IDictionary.Add(object key, object value) {
OnValidate(key, value);
OnInsert(key, value);
InnerHashtable.Add(key, value);
try {
OnInsertComplete(key, value);
}
catch {
InnerHashtable.Remove(key);
throw;
}
}
public void Clear() {
OnClear();
InnerHashtable.Clear();
OnClearComplete();
}
void IDictionary.Remove(object key) {
if(InnerHashtable.Contains(key)) {
Object temp = InnerHashtable[key];
OnValidate(key, temp);
OnRemove(key, temp);
InnerHashtable.Remove(key);
try {
OnRemoveComplete(key, temp);
}
catch {
InnerHashtable.Add(key, temp);
throw;
}
}
}
public IDictionaryEnumerator GetEnumerator() {
return InnerHashtable.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return InnerHashtable.GetEnumerator();
}
protected virtual object OnGet(object key, object currentValue) {
return currentValue;
}
protected virtual void OnSet(object key, object oldValue, object newValue) {
}
protected virtual void OnInsert(object key, object value) {
}
protected virtual void OnClear() {
}
protected virtual void OnRemove(object key, object value) {
}
protected virtual void OnValidate(object key, object value) {
}
protected virtual void OnSetComplete(object key, object oldValue, object newValue) {
}
protected virtual void OnInsertComplete(object key, object value) {
}
protected virtual void OnClearComplete() {
}
protected virtual void OnRemoveComplete(object key, object value) {
}
}
}

View File

@@ -0,0 +1,56 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Interface: DictionaryEntry
**
** <OWNER>[....]</OWNER>
**
**
** Purpose: Return Value for IDictionaryEnumerator::GetEntry
**
**
===========================================================*/
namespace System.Collections {
using System;
// A DictionaryEntry holds a key and a value from a dictionary.
// It is returned by IDictionaryEnumerator::GetEntry().
[System.Runtime.InteropServices.ComVisible(true)]
[Serializable]
public struct DictionaryEntry
{
private Object _key;
private Object _value;
// Constructs a new DictionaryEnumerator by setting the Key
// and Value fields appropriately.
public DictionaryEntry(Object key, Object value) {
_key = key;
_value = value;
}
public Object Key {
get {
return _key;
}
set {
_key = value;
}
}
public Object Value {
get {
return _value;
}
set {
_value = value;
}
}
}
}

View File

@@ -0,0 +1,196 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: EmptyReadOnlyDictionaryInternal
**
** <OWNER>[....]</OWNER>
**
**
** Purpose: List for exceptions.
**
**
===========================================================*/
using System.Diagnostics.Contracts;
namespace System.Collections {
/// This is a simple implementation of IDictionary that is empty and readonly.
[Serializable]
internal sealed class EmptyReadOnlyDictionaryInternal: IDictionary {
// Note that this class must be agile with respect to AppDomains. See its usage in
// System.Exception to understand why this is the case.
public EmptyReadOnlyDictionaryInternal() {
}
// IEnumerable members
IEnumerator IEnumerable.GetEnumerator() {
return new NodeEnumerator();
}
// ICollection members
public void CopyTo(Array array, int index) {
if (array==null)
throw new ArgumentNullException("array");
if (array.Rank != 1)
throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
if (index < 0)
throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
if ( array.Length - index < this.Count )
throw new ArgumentException( Environment.GetResourceString("ArgumentOutOfRange_Index"), "index");
Contract.EndContractBlock();
// the actual copy is a NOP
}
public int Count {
get {
return 0;
}
}
public Object SyncRoot {
get {
return this;
}
}
public bool IsSynchronized {
get {
return false;
}
}
// IDictionary members
public Object this[Object key] {
get {
if (key == null) {
throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
}
Contract.EndContractBlock();
return null;
}
set {
if (key == null) {
throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
}
if (!key.GetType().IsSerializable)
throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "key");
if( (value != null) && (!value.GetType().IsSerializable ) )
throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "value");
Contract.EndContractBlock();
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
}
}
public ICollection Keys {
get {
return EmptyArray<Object>.Value;
}
}
public ICollection Values {
get {
return EmptyArray<Object>.Value;
}
}
public bool Contains(Object key) {
return false;
}
public void Add(Object key, Object value) {
if (key == null) {
throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
}
if (!key.GetType().IsSerializable)
throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "key" );
if( (value != null) && (!value.GetType().IsSerializable) )
throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "value");
Contract.EndContractBlock();
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
}
public void Clear() {
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
}
public bool IsReadOnly {
get {
return true;
}
}
public bool IsFixedSize {
get {
return true;
}
}
public IDictionaryEnumerator GetEnumerator() {
return new NodeEnumerator();
}
public void Remove(Object key) {
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
}
private sealed class NodeEnumerator : IDictionaryEnumerator {
public NodeEnumerator() {
}
// IEnumerator members
public bool MoveNext() {
return false;
}
public Object Current {
get {
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
}
}
public void Reset() {
}
// IDictionaryEnumerator members
public Object Key {
get {
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
}
}
public Object Value {
get {
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
}
}
public DictionaryEntry Entry {
get {
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,169 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// <OWNER>[....]</OWNER>
//
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
//using System.Globalization;
using System.Runtime.CompilerServices;
namespace System.Collections.Generic
{
[Serializable]
[TypeDependencyAttribute("System.Collections.Generic.ObjectComparer`1")]
public abstract class Comparer<T> : IComparer, IComparer<T>
{
static volatile Comparer<T> defaultComparer;
public static Comparer<T> Default {
get {
Contract.Ensures(Contract.Result<Comparer<T>>() != null);
Comparer<T> comparer = defaultComparer;
if (comparer == null) {
comparer = CreateComparer();
defaultComparer = comparer;
}
return comparer;
}
}
public static Comparer<T> Create(Comparison<T> comparison)
{
Contract.Ensures(Contract.Result<Comparer<T>>() != null);
if (comparison == null)
throw new ArgumentNullException("comparison");
return new ComparisonComparer<T>(comparison);
}
//
// Note that logic in this method is replicated in vm\compile.cpp to ensure that NGen
// saves the right instantiations
//
[System.Security.SecuritySafeCritical] // auto-generated
private static Comparer<T> CreateComparer() {
RuntimeType t = (RuntimeType)typeof(T);
// If T implements IComparable<T> return a GenericComparer<T>
#if FEATURE_LEGACYNETCF
// Pre-Apollo Windows Phone call the overload that sorts the keys, not values this achieves the same result
if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {
if (t.ImplementInterface(typeof(IComparable<T>))) {
return (Comparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericComparer<int>), t);
}
}
else
#endif
if (typeof(IComparable<T>).IsAssignableFrom(t)) {
return (Comparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericComparer<int>), t);
}
// If T is a Nullable<U> where U implements IComparable<U> return a NullableComparer<U>
if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)) {
RuntimeType u = (RuntimeType)t.GetGenericArguments()[0];
if (typeof(IComparable<>).MakeGenericType(u).IsAssignableFrom(u)) {
return (Comparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableComparer<int>), u);
}
}
// Otherwise return an ObjectComparer<T>
return new ObjectComparer<T>();
}
public abstract int Compare(T x, T y);
int IComparer.Compare(object x, object y) {
if (x == null) return y == null ? 0 : -1;
if (y == null) return 1;
if (x is T && y is T) return Compare((T)x, (T)y);
ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArgumentForComparison);
return 0;
}
}
[Serializable]
internal class GenericComparer<T> : Comparer<T> where T: IComparable<T>
{
public override int Compare(T x, T y) {
if (x != null) {
if (y != null) return x.CompareTo(y);
return 1;
}
if (y != null) return -1;
return 0;
}
// Equals method for the comparer itself.
public override bool Equals(Object obj){
GenericComparer<T> comparer = obj as GenericComparer<T>;
return comparer != null;
}
public override int GetHashCode() {
return this.GetType().Name.GetHashCode();
}
}
[Serializable]
internal class NullableComparer<T> : Comparer<Nullable<T>> where T : struct, IComparable<T>
{
public override int Compare(Nullable<T> x, Nullable<T> y) {
if (x.HasValue) {
if (y.HasValue) return x.value.CompareTo(y.value);
return 1;
}
if (y.HasValue) return -1;
return 0;
}
// Equals method for the comparer itself.
public override bool Equals(Object obj){
NullableComparer<T> comparer = obj as NullableComparer<T>;
return comparer != null;
}
public override int GetHashCode() {
return this.GetType().Name.GetHashCode();
}
}
[Serializable]
internal class ObjectComparer<T> : Comparer<T>
{
public override int Compare(T x, T y) {
return System.Collections.Comparer.Default.Compare(x, y);
}
// Equals method for the comparer itself.
public override bool Equals(Object obj){
ObjectComparer<T> comparer = obj as ObjectComparer<T>;
return comparer != null;
}
public override int GetHashCode() {
return this.GetType().Name.GetHashCode();
}
}
[Serializable]
internal class ComparisonComparer<T> : Comparer<T>
{
private readonly Comparison<T> _comparison;
public ComparisonComparer(Comparison<T> comparison) {
_comparison = comparison;
}
public override int Compare(T x, T y) {
return _comparison(x, y);
}
}
}

Some files were not shown because too many files have changed in this diff Show More