예제 #1
0
        [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>());
        }
        private static EqualityComparer <T> CreateComparer()
        {
            RuntimeType c = (RuntimeType)typeof(T);

            if (c == typeof(byte))
            {
                return((EqualityComparer <T>) new ByteEqualityComparer());
            }
            if (typeof(IEquatable <T>).IsAssignableFrom(c))
            {
                return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericEqualityComparer <int>), c));
            }
            if (c.IsGenericType && (c.GetGenericTypeDefinition() == typeof(Nullable <>)))
            {
                RuntimeType type2 = (RuntimeType)c.GetGenericArguments()[0];
                if (typeof(IEquatable <>).MakeGenericType(new Type[] { type2 }).IsAssignableFrom(type2))
                {
                    return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableEqualityComparer <int>), type2));
                }
            }
            if (c.IsEnum && (Enum.GetUnderlyingType(c) == typeof(int)))
            {
                return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(EnumEqualityComparer <int>), c));
            }
            return(new ObjectEqualityComparer <T>());
        }
예제 #3
0
        /// <summary>
        /// Creates the default <see cref="EqualityComparer{T}"/> for an enum type.
        /// </summary>
        /// <param name="enumType">The enum type to create the default equality comparer for.</param>
        private static object?TryCreateEnumEqualityComparer(RuntimeType enumType)
        {
            Debug.Assert(enumType != null);
            Debug.Assert(enumType.IsEnum);

            // See the METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST and METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST_LONG cases in getILIntrinsicImplementation
            // for how we cast the enum types to integral values in the comparer without boxing.

            TypeCode underlyingTypeCode = Type.GetTypeCode(Enum.GetUnderlyingType(enumType));

            // Depending on the enum type, we need to special case the comparers so that we avoid boxing.
            switch (underlyingTypeCode)
            {
            case TypeCode.Int32:
            case TypeCode.UInt32:
            case TypeCode.SByte:
            case TypeCode.Byte:
            case TypeCode.Int16:
            case TypeCode.Int64:
            case TypeCode.UInt64:
            case TypeCode.UInt16:
                return(RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(EnumEqualityComparer <>), enumType));
            }

            return(null);
        }
예제 #4
0
파일: Comparer.cs 프로젝트: shrah/coreclr
        //
        // Note that logic in this method is replicated in vm\compile.cpp to ensure that NGen
        // saves the right instantiations
        //
        private static Comparer <T> CreateComparer()
        {
            object      result = null;
            RuntimeType t      = (RuntimeType)typeof(T);

            // If T implements IComparable<T> return a GenericComparer<T>
            if (typeof(IComparable <T>).IsAssignableFrom(t))
            {
                result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericComparer <int>), t);
            }
            else if (default(T) == null)
            {
                // 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))
                    {
                        result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableComparer <int>), u);
                    }
                }
            }
            else if (t.IsEnum)
            {
                // Explicitly call Enum.GetUnderlyingType here. Although GetTypeCode
                // ends up doing this anyway, we end up avoiding an unnecessary P/Invoke
                // and virtual method call.
                TypeCode underlyingTypeCode = Type.GetTypeCode(Enum.GetUnderlyingType(t));

                // Depending on the enum type, we need to special case the comparers so that we avoid boxing
                // Specialize differently for signed/unsigned types so we avoid problems with large numbers
                switch (underlyingTypeCode)
                {
                case TypeCode.SByte:
                case TypeCode.Int16:
                case TypeCode.Int32:
                    result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(Int32EnumComparer <int>), t);
                    break;

                case TypeCode.Byte:
                case TypeCode.UInt16:
                case TypeCode.UInt32:
                    result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(UInt32EnumComparer <uint>), t);
                    break;

                // 64-bit enums: use UnsafeEnumCastLong
                case TypeCode.Int64:
                    result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(Int64EnumComparer <long>), t);
                    break;

                case TypeCode.UInt64:
                    result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(UInt64EnumComparer <ulong>), t);
                    break;
                }
            }

            return(result != null ?
                   (Comparer <T>)result :
                   new ObjectComparer <T>()); // Fallback to ObjectComparer, which uses boxing
        }
예제 #5
0
        [System.Security.SecuritySafeCritical]  // auto-generated
        private static EqualityComparer <T> CreateComparer()
        {
            Contract.Ensures(Contract.Result <EqualityComparer <T> >() != null);

            RuntimeType t = (RuntimeType)typeof(T);

            // Specialize type byte for performance reasons
            if (t == typeof(byte))
            {
                return((EqualityComparer <T>)(object)(new ByteEqualityComparer()));
            }
            // If T implements IEquatable<T> return a GenericEqualityComparer<T>
            if (typeof(IEquatable <T>).IsAssignableFrom(t))
            {
                return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericEqualityComparer <int>), t));
            }
            // If T is a Nullable<U> where U implements IEquatable<U> return a NullableEqualityComparer<U>
            if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                RuntimeType u = (RuntimeType)t.GetGenericArguments()[0];
                if (typeof(IEquatable <>).MakeGenericType(u).IsAssignableFrom(u))
                {
                    return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableEqualityComparer <int>), u));
                }
            }
            // If T is an int-based Enum, return an EnumEqualityComparer<T>
            // See the METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST and METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST_LONG cases in getILIntrinsicImplementation
            if (t.IsEnum && Enum.GetUnderlyingType(t) == typeof(int))
            {
                return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(EnumEqualityComparer <int>), t));
            }
            // Otherwise return an ObjectEqualityComparer<T>
            return(new ObjectEqualityComparer <T>());
        }
예제 #6
0
        [System.Security.SecuritySafeCritical]  // auto-generated
        private static Comparer <T> CreateComparer()
        {
            object      result = null;
            RuntimeType t      = (RuntimeType)typeof(T);

            // If T implements IComparable<T> return a GenericComparer<T>
            if (typeof(IComparable <T>).IsAssignableFrom(t))
            {
                result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericComparer <int>), t);
            }
            else if (default(T) == null)
            {
                // 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))
                    {
                        result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableComparer <int>), u);
                    }
                }
            }

            return(result != null ?
                   (Comparer <T>)result :
                   new ObjectComparer <T>()); // Fallback to ObjectComparer, which uses boxing
        }
예제 #7
0
        /// <summary>
        /// Creates the default <see cref="Comparer{T}"/>.
        /// </summary>
        /// <param name="type">The type to create the default comparer for.</param>
        /// <remarks>
        /// The logic in this method is replicated in vm/compile.cpp to ensure that NGen saves the right instantiations,
        /// and in vm/jitinterface.cpp so the jit can model the behavior of this method.
        /// </remarks>
        internal static object CreateDefaultComparer(Type type)
        {
            Debug.Assert(type != null && type is RuntimeType);

            object?result      = null;
            var    runtimeType = (RuntimeType)type;

            // If T implements IComparable<T> return a GenericComparer<T>
            if (typeof(IComparable <>).MakeGenericType(type).IsAssignableFrom(type))
            {
                result = CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericComparer <int>), runtimeType);
            }
            else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                // Nullable does not implement IComparable<T?> directly because that would add an extra interface call per comparison.
                var embeddedType = (RuntimeType)type.GetGenericArguments()[0];
                result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableComparer <int>), embeddedType);
            }
            // The comparer for enums is specialized to avoid boxing.
            else if (type.IsEnum)
            {
                result = TryCreateEnumComparer(runtimeType);
            }

            return(result ?? CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(ObjectComparer <object>), runtimeType));
        }
예제 #8
0
        /// <summary>
        /// Creates the default <see cref="EqualityComparer{T}"/> for an enum type.
        /// </summary>
        /// <param name="enumType">The enum type to create the default equality comparer for.</param>
        private static object TryCreateEnumEqualityComparer(RuntimeType enumType)
        {
            Debug.Assert(enumType != null);
            Debug.Assert(enumType.IsEnum);

            // See the METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST and METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST_LONG cases in getILIntrinsicImplementation
            // for how we cast the enum types to integral values in the comparer without boxing.

            TypeCode underlyingTypeCode = Type.GetTypeCode(Enum.GetUnderlyingType(enumType));

            // Depending on the enum type, we need to special case the comparers so that we avoid boxing.
            // Note: We have different comparers for short and sbyte, since for those types GetHashCode does not simply return the value.
            // We need to preserve what they would return.
            switch (underlyingTypeCode)
            {
            case TypeCode.Int16:
                return(RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(ShortEnumEqualityComparer <short>), enumType));

            case TypeCode.SByte:
                return(RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(SByteEnumEqualityComparer <sbyte>), enumType));

            case TypeCode.Int32:
            case TypeCode.UInt32:
            case TypeCode.Byte:
            case TypeCode.UInt16:
                return(RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(EnumEqualityComparer <int>), enumType));

            case TypeCode.Int64:
            case TypeCode.UInt64:
                return(RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(LongEnumEqualityComparer <long>), enumType));
            }

            return(null);
        }
예제 #9
0
        /// <summary>
        /// Creates the default <see cref="Comparer{T}"/> for an enum type.
        /// </summary>
        /// <param name="enumType">The enum type to create the default comparer for.</param>
        private static object?TryCreateEnumComparer(RuntimeType enumType)
        {
            Debug.Assert(enumType != null);
            Debug.Assert(enumType.IsEnum);

            // Explicitly call Enum.GetUnderlyingType here. Although GetTypeCode
            // ends up doing this anyway, we end up avoiding an unnecessary P/Invoke
            // and virtual method call.
            TypeCode underlyingTypeCode = Type.GetTypeCode(Enum.GetUnderlyingType(enumType));

            // Depending on the enum type, we need to special case the comparers so that we avoid boxing.
            // Specialize differently for signed/unsigned types so we avoid problems with large numbers.
            switch (underlyingTypeCode)
            {
            case TypeCode.SByte:
            case TypeCode.Int16:
            case TypeCode.Int32:
            case TypeCode.Byte:
            case TypeCode.UInt16:
            case TypeCode.UInt32:
            case TypeCode.Int64:
            case TypeCode.UInt64:
                return(RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(EnumComparer <>), enumType));
            }

            return(null);
        }
예제 #10
0
        [System.Security.SecuritySafeCritical]  // auto-generated
        private static EqualityComparer <T> CreateComparer()
        {
            Contract.Ensures(Contract.Result <EqualityComparer <T> >() != null);

            RuntimeType t = (RuntimeType)typeof(T);//获取泛型格式

            // 用于性能原因的专门类型字节
            if (t == typeof(byte))
            {
                return((EqualityComparer <T>)(object)(new ByteEqualityComparer()));
            }
            // If T implements IEquatable<T> return a GenericEqualityComparer<T>
            // 如果T实现IEquatable<T>,则返回GenericEqualityComparer<T>
            if (typeof(IEquatable <T>).IsAssignableFrom(t))
            {
                return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericEqualityComparer <int>), t));
            }
            // If T is a Nullable<U> where U implements IEquatable<U> return a NullableEqualityComparer<U>
            // 如果T是一个实现了IEquatable<U>的Nullable<U>,将返回一个NullableEqualityComparer<U>
            if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                RuntimeType u = (RuntimeType)t.GetGenericArguments()[0];
                if (typeof(IEquatable <>).MakeGenericType(u).IsAssignableFrom(u))
                {
                    return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableEqualityComparer <int>), u));
                }
            }

            // See the METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST and METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST_LONG cases in getILIntrinsicImplementation
            if (t.IsEnum)
            {
                TypeCode underlyingTypeCode = Type.GetTypeCode(Enum.GetUnderlyingType(t));

                // Depending on the enum type, we need to special case the comparers so that we avoid boxing
                // Note: We have different comparers for Short and SByte because for those types we need to make sure we call GetHashCode on the actual underlying type as the
                // implementation of GetHashCode is more complex than for the other types.
                switch (underlyingTypeCode)
                {
                case TypeCode.Int16:     // short
                    return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(ShortEnumEqualityComparer <short>), t));

                case TypeCode.SByte:
                    return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(SByteEnumEqualityComparer <sbyte>), t));

                case TypeCode.Int32:
                case TypeCode.UInt32:
                case TypeCode.Byte:
                case TypeCode.UInt16:     //ushort
                    return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(EnumEqualityComparer <int>), t));

                case TypeCode.Int64:
                case TypeCode.UInt64:
                    return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(LongEnumEqualityComparer <long>), t));
                }
            }
            // Otherwise return an ObjectEqualityComparer<T>
            return(new ObjectEqualityComparer <T>());
        }
예제 #11
0
        private static IArraySortHelper <T> CreateArraySortHelper()
        {
            IArraySortHelper <T> defaultArraySortHelper;

            if (typeof(IComparable <T>).IsAssignableFrom(typeof(T)))
            {
                defaultArraySortHelper = (IArraySortHelper <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericArraySortHelper <string>), (RuntimeType)typeof(T));
            }
            else
            {
                defaultArraySortHelper = new ArraySortHelper <T>();
            }
            return(defaultArraySortHelper);
        }
예제 #12
0
        /// <summary>
        /// Creates the default <see cref="Comparer{T}"/> for a nullable type.
        /// </summary>
        /// <param name="nullableType">The nullable type to create the default comparer for.</param>
        private static object TryCreateNullableComparer(RuntimeType nullableType)
        {
            Debug.Assert(nullableType != null);
            Debug.Assert(nullableType.IsGenericType && nullableType.GetGenericTypeDefinition() == typeof(Nullable <>));

            var embeddedType = (RuntimeType)nullableType.GetGenericArguments()[0];

            if (typeof(IComparable <>).MakeGenericType(embeddedType).IsAssignableFrom(embeddedType))
            {
                return(RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableComparer <int>), embeddedType));
            }

            return(null);
        }
        private static EqualityComparer <T> CreateComparer()
        {
            RuntimeType runtimeType = (RuntimeType)typeof(T);

            if (runtimeType == typeof(byte))
            {
                return((EqualityComparer <T>) new ByteEqualityComparer());
            }
            if (typeof(IEquatable <T>).IsAssignableFrom(runtimeType))
            {
                return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericEqualityComparer <int>), runtimeType));
            }
            if (runtimeType.IsGenericType && runtimeType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                RuntimeType runtimeType2 = (RuntimeType)runtimeType.GetGenericArguments()[0];
                if (typeof(IEquatable <>).MakeGenericType(new Type[]
                {
                    runtimeType2
                }).IsAssignableFrom(runtimeType2))
                {
                    return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableEqualityComparer <int>), runtimeType2));
                }
            }
            if (runtimeType.IsEnum)
            {
                switch (Type.GetTypeCode(Enum.GetUnderlyingType(runtimeType)))
                {
                case TypeCode.SByte:
                    return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(SByteEnumEqualityComparer <sbyte>), runtimeType));

                case TypeCode.Byte:
                case TypeCode.UInt16:
                case TypeCode.Int32:
                case TypeCode.UInt32:
                    return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(EnumEqualityComparer <int>), runtimeType));

                case TypeCode.Int16:
                    return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(ShortEnumEqualityComparer <short>), runtimeType));

                case TypeCode.Int64:
                case TypeCode.UInt64:
                    return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(LongEnumEqualityComparer <long>), runtimeType));
                }
            }
            return(new ObjectEqualityComparer <T>());
        }
예제 #14
0
        private static Comparer <T> CreateComparer()
        {
            RuntimeType c = (RuntimeType)typeof(T);

            if (typeof(IComparable <T>).IsAssignableFrom(c))
            {
                return((Comparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericComparer <int>), c));
            }
            if (c.IsGenericType && (c.GetGenericTypeDefinition() == typeof(Nullable <>)))
            {
                RuntimeType type2 = (RuntimeType)c.GetGenericArguments()[0];
                if (typeof(IComparable <>).MakeGenericType(new Type[] { type2 }).IsAssignableFrom(type2))
                {
                    return((Comparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableComparer <int>), type2));
                }
            }
            return(new ObjectComparer <T>());
        }
예제 #15
0
        private static Comparer <T> CreateComparer()
        {
            RuntimeType genericParameter1 = (RuntimeType)typeof(T);

            if (typeof(IComparable <T>).IsAssignableFrom((Type)genericParameter1))
            {
                return((Comparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericComparer <int>), genericParameter1));
            }
            if (genericParameter1.IsGenericType && genericParameter1.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                RuntimeType genericParameter2 = (RuntimeType)genericParameter1.GetGenericArguments()[0];
                if (typeof(IComparable <>).MakeGenericType((Type)genericParameter2).IsAssignableFrom((Type)genericParameter2))
                {
                    return((Comparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableComparer <int>), genericParameter2));
                }
            }
            return((Comparer <T>) new ObjectComparer <T>());
        }
예제 #16
0
        [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 (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>());
        }
예제 #17
0
        [System.Security.SecuritySafeCritical]  // auto-generated
        private static EqualityComparer <T> CreateComparer()
        {
            Contract.Ensures(Contract.Result <EqualityComparer <T> >() != null);

            object      result = null;
            RuntimeType t      = (RuntimeType)typeof(T);

            // Specialize type byte for performance reasons
            if (t == typeof(byte))
            {
                result = new ByteEqualityComparer();
            }
            // If T implements IEquatable<T> return a GenericEqualityComparer<T>
            else if (typeof(IEquatable <T>).IsAssignableFrom(t))
            {
                result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericEqualityComparer <int>), t);
            }
            else if (default(T) == null) // Reference type/Nullable
            {
                // If T is a Nullable<U> where U implements IEquatable<U> return a NullableEqualityComparer<U>
                if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable <>))
                {
                    RuntimeType u = (RuntimeType)t.GetGenericArguments()[0];
                    if (typeof(IEquatable <>).MakeGenericType(u).IsAssignableFrom(u))
                    {
                        result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableEqualityComparer <int>), u);
                    }
                }
            }
            // See the METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST and METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST_LONG cases in getILIntrinsicImplementation
            else if (t.IsEnum)
            {
                TypeCode underlyingTypeCode = Type.GetTypeCode(Enum.GetUnderlyingType(t));

                // Depending on the enum type, we need to special case the comparers so that we avoid boxing
                // Note: We have different comparers for Short and SByte because for those types we need to make sure we call GetHashCode on the actual underlying type as the
                // implementation of GetHashCode is more complex than for the other types.
                switch (underlyingTypeCode)
                {
                case TypeCode.Int16:     // short
                    result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(ShortEnumEqualityComparer <short>), t);
                    break;

                case TypeCode.SByte:
                    result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(SByteEnumEqualityComparer <sbyte>), t);
                    break;

                case TypeCode.Int32:
                case TypeCode.UInt32:
                case TypeCode.Byte:
                case TypeCode.UInt16:     //ushort
                    result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(EnumEqualityComparer <int>), t);
                    break;

                case TypeCode.Int64:
                case TypeCode.UInt64:
                    result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(LongEnumEqualityComparer <long>), t);
                    break;
                }
            }

            return(result != null ?
                   (EqualityComparer <T>)result :
                   new ObjectEqualityComparer <T>()); // Fallback to ObjectEqualityComparer, which uses boxing
        }
        [System.Security.SecuritySafeCritical]  // auto-generated
        private static EqualityComparer <T> CreateComparer()
        {
            Contract.Ensures(Contract.Result <EqualityComparer <T> >() != null);

            RuntimeType t = (RuntimeType)typeof(T);

            // Specialize type byte for performance reasons
            if (t == typeof(byte))
            {
                return((EqualityComparer <T>)(object)(new ByteEqualityComparer()));
            }

            /////////////////////////////////////////////////
            // KEEP THIS IN SYNC WITH THE DEVIRT CODE
            // IN METHOD-TO-IR.C
            /////////////////////////////////////////////////
#if MOBILE
            // Breaks .net serialization compatibility
            if (t == typeof(string))
            {
                return((EqualityComparer <T>)(object) new InternalStringComparer());
            }
#endif

            // If T implements IEquatable<T> return a GenericEqualityComparer<T>
            if (typeof(IEquatable <T>).IsAssignableFrom(t))
            {
#if MONO
                return((EqualityComparer <T>)RuntimeType.CreateInstanceForAnotherGenericParameter(typeof(GenericEqualityComparer <>), t));
#else
                return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericEqualityComparer <int>), t));
#endif
            }
            // If T is a Nullable<U> where U implements IEquatable<U> return a NullableEqualityComparer<U>
            if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                RuntimeType u = (RuntimeType)t.GetGenericArguments()[0];
                if (typeof(IEquatable <>).MakeGenericType(u).IsAssignableFrom(u))
                {
#if MONO
                    return((EqualityComparer <T>)RuntimeType.CreateInstanceForAnotherGenericParameter(typeof(NullableEqualityComparer <>), u));
#else
                    return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableEqualityComparer <int>), u));
#endif
                }
            }

            // See the METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST and METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST_LONG cases in getILIntrinsicImplementation
            if (t.IsEnum)
            {
                TypeCode underlyingTypeCode = Type.GetTypeCode(Enum.GetUnderlyingType(t));

                // Depending on the enum type, we need to special case the comparers so that we avoid boxing
                // Note: We have different comparers for Short and SByte because for those types we need to make sure we call GetHashCode on the actual underlying type as the
                // implementation of GetHashCode is more complex than for the other types.
                switch (underlyingTypeCode)
                {
                case TypeCode.Int16:     // short
#if MONO
                    return((EqualityComparer <T>)RuntimeType.CreateInstanceForAnotherGenericParameter(typeof(ShortEnumEqualityComparer <>), t));
#else
                    return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(ShortEnumEqualityComparer <short>), t));
#endif
                case TypeCode.SByte:
#if MONO
                    return((EqualityComparer <T>)RuntimeType.CreateInstanceForAnotherGenericParameter(typeof(SByteEnumEqualityComparer <>), t));
#else
                    return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(SByteEnumEqualityComparer <sbyte>), t));
#endif
                case TypeCode.Int32:
                case TypeCode.UInt32:
                case TypeCode.Byte:
                case TypeCode.UInt16:     //ushort
#if MONO
                    return((EqualityComparer <T>)RuntimeType.CreateInstanceForAnotherGenericParameter(typeof(EnumEqualityComparer <>), t));
#else
                    return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(EnumEqualityComparer <int>), t));
#endif
                case TypeCode.Int64:
                case TypeCode.UInt64:
#if MONO
                    return((EqualityComparer <T>)RuntimeType.CreateInstanceForAnotherGenericParameter(typeof(LongEnumEqualityComparer <>), t));
#else
                    return((EqualityComparer <T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(LongEnumEqualityComparer <long>), t));
#endif
                }
            }
            // Otherwise return an ObjectEqualityComparer<T>
            return(new ObjectEqualityComparer <T>());
        }