The Labs \ Source Viewer \ SSCLI \ System.Collections.Generic \ Comparer

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. using System;
  16. using System.Collections;
  17. using System.Collections.Generic;
  18. namespace System.Collections.Generic
  19. {
  20.     using System.Globalization;
  21.     using System.Runtime.CompilerServices;
  22.    
  23.     [Serializable()]
  24.     [TypeDependencyAttribute("System.Collections.Generic.GenericComparer`1")]
  25.     public abstract class Comparer<T> : IComparer, IComparer<T>
  26.     {
  27.         static Comparer<T> defaultComparer;
  28.        
  29.         public static Comparer<T> Default {
  30.             get {
  31.                 Comparer<T> comparer = defaultComparer;
  32.                 if (comparer == null) {
  33.                     comparer = CreateComparer();
  34.                     defaultComparer = comparer;
  35.                 }
  36.                 return comparer;
  37.             }
  38.         }
  39.        
  40.         private static Comparer<T> CreateComparer()
  41.         {
  42.             Type t = typeof(T);
  43.             // If T implements IComparable<T> return a GenericComparer<T>
  44.             if (typeof(IComparable<T>).IsAssignableFrom(t)) {
  45.                 //return (Comparer<T>)Activator.CreateInstance(typeof(GenericComparer<>).MakeGenericType(t));
  46.                 return (Comparer<T>)(typeof(GenericComparer<int>).TypeHandle.CreateInstanceForAnotherGenericParameter(t));
  47.             }
  48.             // If T is a Nullable<U> where U implements IComparable<U> return a NullableComparer<U>
  49.             if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)) {
  50.                 Type u = t.GetGenericArguments()[0];
  51.                 if (typeof(IComparable<>).MakeGenericType(u).IsAssignableFrom(u)) {
  52.                     //return (Comparer<T>)Activator.CreateInstance(typeof(NullableComparer<>).MakeGenericType(u));
  53.                     return (Comparer<T>)(typeof(NullableComparer<int>).TypeHandle.CreateInstanceForAnotherGenericParameter(u));
  54.                 }
  55.             }
  56.             // Otherwise return an ObjectComparer<T>
  57.             return new ObjectComparer<T>();
  58.         }
  59.        
  60.         public abstract int Compare(T x, T y);
  61.        
  62.         int IComparer.Compare(object x, object y)
  63.         {
  64.             if (x == null)
  65.                 return y == null ? 0 : -1;
  66.             if (y == null)
  67.                 return 1;
  68.             if (x is T && y is T)
  69.                 return Compare((T)x, (T)y);
  70.             ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArgumentForComparison);
  71.             return 0;
  72.         }
  73.     }
  74.    
  75.     [Serializable()]
  76.     internal class GenericComparer<T> : Comparer<T> where T : IComparable<T>
  77.     {
  78.         public override int Compare(T x, T y)
  79.         {
  80.             if (x != null) {
  81.                 if (y != null)
  82.                     return x.CompareTo(y);
  83.                 return 1;
  84.             }
  85.             if (y != null)
  86.                 return -1;
  87.             return 0;
  88.         }
  89.        
  90.         // Equals method for the comparer itself.
  91.         public override bool Equals(object obj)
  92.         {
  93.             GenericComparer<T> comparer = obj as GenericComparer<T>;
  94.             return comparer != null;
  95.         }
  96.        
  97.         public override int GetHashCode()
  98.         {
  99.             return this.GetType().Name.GetHashCode();
  100.         }
  101.     }
  102.    
  103.     [Serializable()]
  104.     internal class NullableComparer<T> : Comparer<Nullable<T>> where T : struct, IComparable<T>
  105.     {
  106.         public override int Compare(Nullable<T> x, Nullable<T> y)
  107.         {
  108.             if (x.HasValue) {
  109.                 if (y.HasValue)
  110.                     return x.value.CompareTo(y.value);
  111.                 return 1;
  112.             }
  113.             if (y.HasValue)
  114.                 return -1;
  115.             return 0;
  116.         }
  117.        
  118.         // Equals method for the comparer itself.
  119.         public override bool Equals(object obj)
  120.         {
  121.             NullableComparer<T> comparer = obj as NullableComparer<T>;
  122.             return comparer != null;
  123.         }
  124.        
  125.         public override int GetHashCode()
  126.         {
  127.             return this.GetType().Name.GetHashCode();
  128.         }
  129.     }
  130.    
  131.     [Serializable()]
  132.     internal class ObjectComparer<T> : Comparer<T>
  133.     {
  134.         public override int Compare(T x, T y)
  135.         {
  136.             return System.Collections.Comparer.Default.Compare(x, y);
  137.         }
  138.        
  139.         // Equals method for the comparer itself.
  140.         public override bool Equals(object obj)
  141.         {
  142.             ObjectComparer<T> comparer = obj as ObjectComparer<T>;
  143.             return comparer != null;
  144.         }
  145.        
  146.         public override int GetHashCode()
  147.         {
  148.             return this.GetType().Name.GetHashCode();
  149.         }
  150.     }
  151. }

Developer Fusion