EqualityComparer.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Collections / Generic / EqualityComparer.cs / 1305376 / EqualityComparer.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
// [....]
// 
 
using System;
using System.Collections; 
using System.Collections.Generic;

namespace System.Collections.Generic
{ 
    using System.Globalization;
    using System.Runtime; 
    using System.Runtime.CompilerServices; 
    using System.Diagnostics.Contracts;
 
    [Serializable]
    [TypeDependencyAttribute("System.Collections.Generic.GenericEqualityComparer`1")]
    [TypeDependencyAttribute("System.Collections.Generic.EnumEqualityComparer`1")]
    public abstract class EqualityComparer : IEqualityComparer, IEqualityComparer 
    {
        static EqualityComparer defaultComparer; 
 
        public static EqualityComparer Default {
            [System.Security.SecuritySafeCritical]  // auto-generated 
#if !FEATURE_CORECLR
            [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
#endif
            get { 
                Contract.Ensures(Contract.Result>() != null);
 
                EqualityComparer comparer = defaultComparer; 
                if (comparer == null) {
                    comparer = CreateComparer(); 
                    defaultComparer = comparer;
                }
                return comparer;
            } 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        private static EqualityComparer CreateComparer() {
            Contract.Ensures(Contract.Result>() != null); 

            RuntimeType t = (RuntimeType)typeof(T);
            // Specialize type byte for performance reasons
            if (t == typeof(byte)) { 
                return (EqualityComparer)(object)(new ByteEqualityComparer());
            } 
            // If T implements IEquatable return a GenericEqualityComparer 
            if (typeof(IEquatable).IsAssignableFrom(t)) {
                //return (EqualityComparer)Activator.CreateInstance(typeof(GenericEqualityComparer<>).MakeGenericType(t)); 
                return (EqualityComparer)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericEqualityComparer), t);
            }
            // If T is a Nullable where U implements IEquatable return a NullableEqualityComparer
            if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)) { 
                RuntimeType u = (RuntimeType)t.GetGenericArguments()[0];
                if (typeof(IEquatable<>).MakeGenericType(u).IsAssignableFrom(u)) { 
                    //return (EqualityComparer)Activator.CreateInstance(typeof(NullableEqualityComparer<>).MakeGenericType(u)); 
                    return (EqualityComparer)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableEqualityComparer), u);
                } 
            }
            // If T is an int-based Enum, return an EnumEqualityComparer
            // If you update this check, you need to update the METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST case in getILIntrinsicImplementation
            if (t.IsEnum && Enum.GetUnderlyingType(t) == typeof(int)) 
            {
                return (EqualityComparer)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(EnumEqualityComparer), t); 
            } 
            // Otherwise return an ObjectEqualityComparer
            return new ObjectEqualityComparer(); 
        }

        [Pure]
        public abstract bool Equals(T x, T y); 
        [Pure]
        public abstract int GetHashCode(T obj); 
 
        internal virtual int IndexOf(T[] array, T value, int startIndex, int count) {
            int endIndex = startIndex + count; 
            for (int i = startIndex; i < endIndex; i++) {
                if (Equals(array[i], value)) return i;
            }
            return -1; 
        }
 
        internal virtual int LastIndexOf(T[] array, T value, int startIndex, int count) { 
            int endIndex = startIndex - count + 1;
            for (int i = startIndex; i >= endIndex; i--) { 
                if (Equals(array[i], value)) return i;
            }
            return -1;
        } 

        int IEqualityComparer.GetHashCode(object obj) { 
            if (obj == null) return 0; 
            if (obj is T) return GetHashCode((T)obj);
            ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArgumentForComparison); 
            return 0;
        }

        bool IEqualityComparer.Equals(object x, object y) { 
            if (x == y) return true;
            if (x == null || y == null) return false; 
            if ((x is T) && (y is T)) return Equals((T)x, (T)y); 
            ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArgumentForComparison);
            return false; 
        }
    }

    // The methods in this class look identical to the inherited methods, but the calls 
    // to Equal bind to IEquatable.Equals(T) instead of Object.Equals(Object)
    [Serializable] 
    internal class GenericEqualityComparer: EqualityComparer where T: IEquatable 
    {
        [Pure] 
        public override bool Equals(T x, T y) {
            if (x != null) {
                if (y != null) return x.Equals(y);
                return false; 
            }
            if (y != null) return false; 
            return true; 
        }
 
        [Pure]
#if !FEATURE_CORECLR
        [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
#endif 
        public override int GetHashCode(T obj) {
            if (obj == null) return 0; 
            return obj.GetHashCode(); 
        }
 
        internal override int IndexOf(T[] array, T value, int startIndex, int count) {
            int endIndex = startIndex + count;
            if (value == null) {
                for (int i = startIndex; i < endIndex; i++) { 
                    if (array[i] == null) return i;
                } 
            } 
            else {
                for (int i = startIndex; i < endIndex; i++) { 
                    if (array[i] != null && array[i].Equals(value)) return i;
                }
            }
            return -1; 
        }
 
        internal override int LastIndexOf(T[] array, T value, int startIndex, int count) { 
            int endIndex = startIndex - count + 1;
            if (value == null) { 
                for (int i = startIndex; i >= endIndex; i--) {
                    if (array[i] == null) return i;
                }
            } 
            else {
                for (int i = startIndex; i >= endIndex; i--) { 
                    if (array[i] != null && array[i].Equals(value)) return i; 
                }
            } 
            return -1;
        }

        // Equals method for the comparer itself. 
        public override bool Equals(Object obj){
            GenericEqualityComparer comparer = obj as GenericEqualityComparer; 
            return comparer != null; 
        }
 
        public override int GetHashCode() {
            return this.GetType().Name.GetHashCode();
        }
    } 

    [Serializable] 
    internal class NullableEqualityComparer : EqualityComparer> where T : struct, IEquatable 
    {
        [Pure] 
        public override bool Equals(Nullable x, Nullable y) {
            if (x.HasValue) {
                if (y.HasValue) return x.value.Equals(y.value);
                return false; 
            }
            if (y.HasValue) return false; 
            return true; 
        }
 
        [Pure]
        public override int GetHashCode(Nullable obj) {
            return obj.GetHashCode();
        } 

        internal override int IndexOf(Nullable[] array, Nullable value, int startIndex, int count) { 
            int endIndex = startIndex + count; 
            if (!value.HasValue) {
                for (int i = startIndex; i < endIndex; i++) { 
                    if (!array[i].HasValue) return i;
                }
            }
            else { 
                for (int i = startIndex; i < endIndex; i++) {
                    if (array[i].HasValue && array[i].value.Equals(value.value)) return i; 
                } 
            }
            return -1; 
        }

        internal override int LastIndexOf(Nullable[] array, Nullable value, int startIndex, int count) {
            int endIndex = startIndex - count + 1; 
            if (!value.HasValue) {
                for (int i = startIndex; i >= endIndex; i--) { 
                    if (!array[i].HasValue) return i; 
                }
            } 
            else {
                for (int i = startIndex; i >= endIndex; i--) {
                    if (array[i].HasValue && array[i].value.Equals(value.value)) return i;
                } 
            }
            return -1; 
        } 

        // Equals method for the comparer itself. 
        public override bool Equals(Object obj){
            NullableEqualityComparer comparer = obj as NullableEqualityComparer;
            return comparer != null;
        } 

        public override int GetHashCode() { 
            return this.GetType().Name.GetHashCode(); 
        }
    } 

    [Serializable]
    internal class ObjectEqualityComparer: EqualityComparer
    { 
        [Pure]
        public override bool Equals(T x, T y) { 
            if (x != null) { 
                if (y != null) return x.Equals(y);
                return false; 
            }
            if (y != null) return false;
            return true;
        } 

        [Pure] 
#if !FEATURE_CORECLR 
        [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
#endif 
        public override int GetHashCode(T obj) {
            if (obj == null) return 0;
            return obj.GetHashCode();
        } 

        internal override int IndexOf(T[] array, T value, int startIndex, int count) { 
            int endIndex = startIndex + count; 
            if (value == null) {
                for (int i = startIndex; i < endIndex; i++) { 
                    if (array[i] == null) return i;
                }
            }
            else { 
                for (int i = startIndex; i < endIndex; i++) {
                    if (array[i] != null && array[i].Equals(value)) return i; 
                } 
            }
            return -1; 
        }

        internal override int LastIndexOf(T[] array, T value, int startIndex, int count) {
            int endIndex = startIndex - count + 1; 
            if (value == null) {
                for (int i = startIndex; i >= endIndex; i--) { 
                    if (array[i] == null) return i; 
                }
            } 
            else {
                for (int i = startIndex; i >= endIndex; i--) {
                    if (array[i] != null && array[i].Equals(value)) return i;
                } 
            }
            return -1; 
        } 

        // Equals method for the comparer itself. 
        public override bool Equals(Object obj){
            ObjectEqualityComparer comparer = obj as ObjectEqualityComparer;
            return comparer != null;
        } 

        public override int GetHashCode() { 
            return this.GetType().Name.GetHashCode(); 
        }
    } 

    // Performance of IndexOf on byte array is very important for some scenarios.
    // We will call the C runtime function memchr, which is optimized.
    [Serializable] 
    internal class ByteEqualityComparer: EqualityComparer
    { 
        [Pure] 
        public override bool Equals(byte x, byte y) {
            return x == y; 
        }

        [Pure]
        public override int GetHashCode(byte b) { 
            return b.GetHashCode();
        } 
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal unsafe override int IndexOf(byte[] array, byte value, int startIndex, int count) { 
            if (array==null)
                throw new ArgumentNullException("array");
            if (startIndex < 0)
                throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); 
            if (count < 0)
                throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); 
            if (count > array.Length - startIndex) 
                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
            Contract.EndContractBlock(); 
            if (count == 0) return -1;
            fixed (byte* pbytes = array) {
                return Buffer.IndexOfByte(pbytes, value, startIndex, count);
            } 
        }
 
        internal override int LastIndexOf(byte[] array, byte value, int startIndex, int count) { 
            int endIndex = startIndex - count + 1;
            for (int i = startIndex; i >= endIndex; i--) { 
                if (array[i] == value) return i;
            }
            return -1;
        } 

        // Equals method for the comparer itself. 
        public override bool Equals(Object obj){ 
            ByteEqualityComparer comparer = obj as ByteEqualityComparer;
            return comparer != null; 
        }

        public override int GetHashCode() {
            return this.GetType().Name.GetHashCode(); 
        }
 
    } 

    [Serializable] 
    internal sealed class EnumEqualityComparer: EqualityComparer where T: struct
    {
        [Pure]
        [System.Security.SecuritySafeCritical] 
        public override bool Equals(T x, T y) {
            int x_final = System.Runtime.CompilerServices.JitHelpers.UnsafeEnumCast(x); 
            int y_final = System.Runtime.CompilerServices.JitHelpers.UnsafeEnumCast(y); 
            return x_final == y_final;
        } 

        [Pure]
        [System.Security.SecuritySafeCritical]
        public override int GetHashCode(T obj) { 
            int x_final = System.Runtime.CompilerServices.JitHelpers.UnsafeEnumCast(obj);
            return x_final.GetHashCode(); 
        } 

        // Equals method for the comparer itself. 
        public override bool Equals(Object obj){
            EnumEqualityComparer comparer = obj as EnumEqualityComparer;
            return comparer != null;
        } 

        public override int GetHashCode() { 
            return this.GetType().Name.GetHashCode(); 
        }
    } 
}


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK