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

  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.GenericEqualityComparer`1")]
  25.     public abstract class EqualityComparer<T> : IEqualityComparer, IEqualityComparer<T>
  26.     {
  27.         static EqualityComparer<T> defaultComparer;
  28.        
  29.         public static EqualityComparer<T> Default {
  30.             get {
  31.                 EqualityComparer<T> comparer = defaultComparer;
  32.                 if (comparer == null) {
  33.                     comparer = CreateComparer();
  34.                     defaultComparer = comparer;
  35.                 }
  36.                 return comparer;
  37.             }
  38.         }
  39.        
  40.         private static EqualityComparer<T> CreateComparer()
  41.         {
  42.             Type t = typeof(T);
  43.             // Specialize type byte for performance reasons
  44.             if (t == typeof(byte)) {
  45.                 return (EqualityComparer<T>)(object)(new ByteEqualityComparer());
  46.             }
  47.             // If T implements IEquatable<T> return a GenericEqualityComparer<T>
  48.             if (typeof(IEquatable<T>).IsAssignableFrom(t)) {
  49.                 //return (EqualityComparer<T>)Activator.CreateInstance(typeof(GenericEqualityComparer<>).MakeGenericType(t));
  50.                 return (EqualityComparer<T>)(typeof(GenericEqualityComparer<int>).TypeHandle.CreateInstanceForAnotherGenericParameter(t));
  51.             }
  52.             // If T is a Nullable<U> where U implements IEquatable<U> return a NullableEqualityComparer<U>
  53.             if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)) {
  54.                 Type u = t.GetGenericArguments()[0];
  55.                 if (typeof(IEquatable<>).MakeGenericType(u).IsAssignableFrom(u)) {
  56.                     //return (EqualityComparer<T>)Activator.CreateInstance(typeof(NullableEqualityComparer<>).MakeGenericType(u));
  57.                     return (EqualityComparer<T>)(typeof(NullableEqualityComparer<int>).TypeHandle.CreateInstanceForAnotherGenericParameter(u));
  58.                 }
  59.             }
  60.             // Otherwise return an ObjectEqualityComparer<T>
  61.             return new ObjectEqualityComparer<T>();
  62.         }
  63.        
  64.         public abstract bool Equals(T x, T y);
  65.         public abstract int GetHashCode(T obj);
  66.        
  67.         internal virtual int IndexOf(T[] array, T value, int startIndex, int count)
  68.         {
  69.             int endIndex = startIndex + count;
  70.             for (int i = startIndex; i < endIndex; i++) {
  71.                 if (Equals(array[i], value))
  72.                     return i;
  73.             }
  74.             return -1;
  75.         }
  76.        
  77.         internal virtual int LastIndexOf(T[] array, T value, int startIndex, int count)
  78.         {
  79.             int endIndex = startIndex - count + 1;
  80.             for (int i = startIndex; i >= endIndex; i--) {
  81.                 if (Equals(array[i], value))
  82.                     return i;
  83.             }
  84.             return -1;
  85.         }
  86.        
  87.         int IEqualityComparer.GetHashCode(object obj)
  88.         {
  89.             if (obj == null)
  90.                 return 0;
  91.             if (obj is T)
  92.                 return GetHashCode((T)obj);
  93.             ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArgumentForComparison);
  94.             return 0;
  95.         }
  96.        
  97.         bool IEqualityComparer.Equals(object x, object y)
  98.         {
  99.             if (x == y)
  100.                 return true;
  101.             if (x == null || y == null)
  102.                 return false;
  103.             if ((x is T) && (y is T))
  104.                 return Equals((T)x, (T)y);
  105.             ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArgumentForComparison);
  106.             return false;
  107.         }
  108.     }
  109.    
  110.     // The methods in this class look identical to the inherited methods, but the calls
  111.     // to Equal bind to IEquatable<T>.Equals(T) instead of Object.Equals(Object)
  112.     [Serializable()]
  113.     internal class GenericEqualityComparer<T> : EqualityComparer<T> where T : IEquatable<T>
  114.     {
  115.         public override bool Equals(T x, T y)
  116.         {
  117.             if (x != null) {
  118.                 if (y != null)
  119.                     return x.Equals(y);
  120.                 return false;
  121.             }
  122.             if (y != null)
  123.                 return false;
  124.             return true;
  125.         }
  126.        
  127.         public override int GetHashCode(T obj)
  128.         {
  129.             if (obj == null)
  130.                 return 0;
  131.             return obj.GetHashCode();
  132.         }
  133.        
  134.         internal override int IndexOf(T[] array, T value, int startIndex, int count)
  135.         {
  136.             int endIndex = startIndex + count;
  137.             if (value == null) {
  138.                 for (int i = startIndex; i < endIndex; i++) {
  139.                     if (array[i] == null)
  140.                         return i;
  141.                 }
  142.             }
  143.             else {
  144.                 for (int i = startIndex; i < endIndex; i++) {
  145.                     if (array[i] != null && array[i].Equals(value))
  146.                         return i;
  147.                 }
  148.             }
  149.             return -1;
  150.         }
  151.        
  152.         internal override int LastIndexOf(T[] array, T value, int startIndex, int count)
  153.         {
  154.             int endIndex = startIndex - count + 1;
  155.             if (value == null) {
  156.                 for (int i = startIndex; i >= endIndex; i--) {
  157.                     if (array[i] == null)
  158.                         return i;
  159.                 }
  160.             }
  161.             else {
  162.                 for (int i = startIndex; i >= endIndex; i--) {
  163.                     if (array[i] != null && array[i].Equals(value))
  164.                         return i;
  165.                 }
  166.             }
  167.             return -1;
  168.         }
  169.        
  170.         // Equals method for the comparer itself.
  171.         public override bool Equals(object obj)
  172.         {
  173.             GenericEqualityComparer<T> comparer = obj as GenericEqualityComparer<T>;
  174.             return comparer != null;
  175.         }
  176.        
  177.         public override int GetHashCode()
  178.         {
  179.             return this.GetType().Name.GetHashCode();
  180.         }
  181.     }
  182.    
  183.     [Serializable()]
  184.     internal class NullableEqualityComparer<T> : EqualityComparer<Nullable<T>> where T : struct, IEquatable<T>
  185.     {
  186.         public override bool Equals(Nullable<T> x, Nullable<T> y)
  187.         {
  188.             if (x.HasValue) {
  189.                 if (y.HasValue)
  190.                     return x.value.Equals(y.value);
  191.                 return false;
  192.             }
  193.             if (y.HasValue)
  194.                 return false;
  195.             return true;
  196.         }
  197.        
  198.         public override int GetHashCode(Nullable<T> obj)
  199.         {
  200.             return obj.GetHashCode();
  201.         }
  202.        
  203.         internal override int IndexOf(Nullable<T>[] array, Nullable<T> value, int startIndex, int count)
  204.         {
  205.             int endIndex = startIndex + count;
  206.             if (!value.HasValue) {
  207.                 for (int i = startIndex; i < endIndex; i++) {
  208.                     if (!array[i].HasValue)
  209.                         return i;
  210.                 }
  211.             }
  212.             else {
  213.                 for (int i = startIndex; i < endIndex; i++) {
  214.                     if (array[i].HasValue && array[i].value.Equals(value.value))
  215.                         return i;
  216.                 }
  217.             }
  218.             return -1;
  219.         }
  220.        
  221.         internal override int LastIndexOf(Nullable<T>[] array, Nullable<T> value, int startIndex, int count)
  222.         {
  223.             int endIndex = startIndex - count + 1;
  224.             if (!value.HasValue) {
  225.                 for (int i = startIndex; i >= endIndex; i--) {
  226.                     if (!array[i].HasValue)
  227.                         return i;
  228.                 }
  229.             }
  230.             else {
  231.                 for (int i = startIndex; i >= endIndex; i--) {
  232.                     if (array[i].HasValue && array[i].value.Equals(value.value))
  233.                         return i;
  234.                 }
  235.             }
  236.             return -1;
  237.         }
  238.        
  239.         // Equals method for the comparer itself.
  240.         public override bool Equals(object obj)
  241.         {
  242.             NullableEqualityComparer<T> comparer = obj as NullableEqualityComparer<T>;
  243.             return comparer != null;
  244.         }
  245.        
  246.         public override int GetHashCode()
  247.         {
  248.             return this.GetType().Name.GetHashCode();
  249.         }
  250.     }
  251.    
  252.     [Serializable()]
  253.     internal class ObjectEqualityComparer<T> : EqualityComparer<T>
  254.     {
  255.         public override bool Equals(T x, T y)
  256.         {
  257.             if (x != null) {
  258.                 if (y != null)
  259.                     return x.Equals(y);
  260.                 return false;
  261.             }
  262.             if (y != null)
  263.                 return false;
  264.             return true;
  265.         }
  266.        
  267.         public override int GetHashCode(T obj)
  268.         {
  269.             if (obj == null)
  270.                 return 0;
  271.             return obj.GetHashCode();
  272.         }
  273.        
  274.         internal override int IndexOf(T[] array, T value, int startIndex, int count)
  275.         {
  276.             int endIndex = startIndex + count;
  277.             if (value == null) {
  278.                 for (int i = startIndex; i < endIndex; i++) {
  279.                     if (array[i] == null)
  280.                         return i;
  281.                 }
  282.             }
  283.             else {
  284.                 for (int i = startIndex; i < endIndex; i++) {
  285.                     if (array[i] != null && array[i].Equals(value))
  286.                         return i;
  287.                 }
  288.             }
  289.             return -1;
  290.         }
  291.        
  292.         internal override int LastIndexOf(T[] array, T value, int startIndex, int count)
  293.         {
  294.             int endIndex = startIndex - count + 1;
  295.             if (value == null) {
  296.                 for (int i = startIndex; i >= endIndex; i--) {
  297.                     if (array[i] == null)
  298.                         return i;
  299.                 }
  300.             }
  301.             else {
  302.                 for (int i = startIndex; i >= endIndex; i--) {
  303.                     if (array[i] != null && array[i].Equals(value))
  304.                         return i;
  305.                 }
  306.             }
  307.             return -1;
  308.         }
  309.        
  310.         // Equals method for the comparer itself.
  311.         public override bool Equals(object obj)
  312.         {
  313.             ObjectEqualityComparer<T> comparer = obj as ObjectEqualityComparer<T>;
  314.             return comparer != null;
  315.         }
  316.        
  317.         public override int GetHashCode()
  318.         {
  319.             return this.GetType().Name.GetHashCode();
  320.         }
  321.     }
  322.    
  323.     // Performance of IndexOf on byte array is very important for some scenarios.
  324.     // We will call the C runtime function memchr, which is optimized.
  325.     [Serializable()]
  326.     internal class ByteEqualityComparer : EqualityComparer<byte>
  327.     {
  328.         public override bool Equals(byte x, byte y)
  329.         {
  330.             return x == y;
  331.         }
  332.        
  333.         public override int GetHashCode(byte b)
  334.         {
  335.             return b.GetHashCode();
  336.         }
  337.        
  338.         unsafe internal override int IndexOf(byte[] array, byte value, int startIndex, int count)
  339.         {
  340.             if (array == null)
  341.                 throw new ArgumentNullException("array");
  342.             if (startIndex < 0)
  343.                 throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
  344.             if (count < 0)
  345.                 throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count"));
  346.             if (count > array.Length - startIndex)
  347.                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
  348.             if (count == 0)
  349.                 return -1;
  350.             fixed (byte* pbytes = array) {
  351.                 return Buffer.IndexOfByte(pbytes, value, startIndex, count);
  352.             }
  353.         }
  354.        
  355.         internal override int LastIndexOf(byte[] array, byte value, int startIndex, int count)
  356.         {
  357.             int endIndex = startIndex - count + 1;
  358.             for (int i = startIndex; i >= endIndex; i--) {
  359.                 if (array[i] == value)
  360.                     return i;
  361.             }
  362.             return -1;
  363.         }
  364.        
  365.         // Equals method for the comparer itself.
  366.         public override bool Equals(object obj)
  367.         {
  368.             ByteEqualityComparer comparer = obj as ByteEqualityComparer;
  369.             return comparer != null;
  370.         }
  371.        
  372.         public override int GetHashCode()
  373.         {
  374.             return this.GetType().Name.GetHashCode();
  375.         }
  376.        
  377.     }
  378. }

Developer Fusion