Imported Upstream version 4.6.0.125

Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2016-08-03 10:59:49 +00:00
parent a569aebcfd
commit e79aa3c0ed
17047 changed files with 3137615 additions and 392334 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
}

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"));
}
}
}

View File

@@ -0,0 +1 @@
0e7b25c8eec5ef2270f833d3acd6e2faa65156b0

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,177 @@
// ==++==
//
// 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)) {
#if MONO
return (Comparer<T>)RuntimeType.CreateInstanceForAnotherGenericParameter (typeof(GenericComparer<>), t);
#else
return (Comparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericComparer<int>), t);
#endif
}
// 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)) {
#if MONO
return (Comparer<T>)RuntimeType.CreateInstanceForAnotherGenericParameter (typeof(NullableComparer<>), u);
#else
return (Comparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableComparer<int>), u);
#endif
}
}
// 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