private static EqualityComparer <T> CreateComparer()
        {
            RuntimeType t = (RuntimeType)typeof(T);

            /////////////////////////////////////////////////
            // KEEP THIS IN SYNC WITH THE DEVIRT CODE
            // IN METHOD-TO-IR.C
            /////////////////////////////////////////////////

            if (t == typeof(byte))
            {
                return((EqualityComparer <T>)(object)(new ByteEqualityComparer()));
            }

            if (typeof(IEquatable <T>).IsAssignableFrom(t))
            {
                return((EqualityComparer <T>)RuntimeType.CreateInstanceForAnotherGenericParameter(typeof(GenericEqualityComparer <>), t));
            }

            if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                RuntimeType u = (RuntimeType)t.GetGenericArguments()[0];
                if (typeof(IEquatable <>).MakeGenericType(u).IsAssignableFrom(u))
                {
                    return((EqualityComparer <T>)RuntimeType.CreateInstanceForAnotherGenericParameter(typeof(NullableEqualityComparer <>), u));
                }
            }

            if (t.IsEnum)
            {
                return((EqualityComparer <T>)RuntimeType.CreateInstanceForAnotherGenericParameter(typeof(EnumEqualityComparer <>), t));
            }

            return(new ObjectEqualityComparer <T>());
        }
Example #2
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
        }
Example #3
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>());
        }
        internal ushort GetTypeSeq(TypeMap typeMap, BinarySerializerOptions options)
        {
            Debug.Assert(RuntimeType != null);
            Debug.Assert(typeMap != null);

            bool isAdd = typeMap.TryAdd(RuntimeType, out BinaryTypeInfo ti);

            if (isAdd || ti.Type == TypeEnum.None)
            {
                ti.IsGeneric            = RuntimeType.IsGenericType;
                ti.GenericArgumentCount = RuntimeType.GetGenericArgumentCount();
                if (ti.GenericArgumentCount > 0)
                {
                    ti.GenericArguments = RuntimeType.GetGenericArguments()
                                          .Select(t =>
                    {
                        var converter = options.GetConverter(t);
                        Debug.Assert(converter != null);
                        return(converter.GetTypeSeq(typeMap, options));
                    }).ToArray();
                }
                SetTypeMetadata(ti, typeMap, options);
            }

            return(ti.Seq);
        }
        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>());
        }
Example #6
0
        static Comparer <T> CreateComparer()
        {
            RuntimeType t = (RuntimeType)typeof(T);

            if (typeof(IComparable <T>).IsAssignableFrom(t))
            {
                return((Comparer <T>)RuntimeType.CreateInstanceForAnotherGenericParameter(typeof(GenericComparer <>), 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>)RuntimeType.CreateInstanceForAnotherGenericParameter(typeof(NullableComparer <>), u));
                }
            }

            if (t.IsEnum)
            {
                return((Comparer <T>)RuntimeType.CreateInstanceForAnotherGenericParameter(typeof(EnumComparer <>), t));
            }

            // Otherwise return an ObjectComparer<T>
            return(new ObjectComparer <T> ());
        }
Example #7
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>());
        }
Example #8
0
        //
        // 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
        }
Example #9
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>());
        }
Example #10
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>());
        }
Example #12
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>());
        }
Example #13
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>());
        }
Example #14
0
        object CreateInstance()
        {
            if (RuntimeType.IsInterface)
            {
                if (RuntimeType.IsGenericType && Array.IndexOf(RuntimeType.GetGenericTypeDefinition().GetInterfaces(), typeof(IDictionary <,>)) >= 0)
                {
                    var gargs = RuntimeType.GetGenericArguments();
                    return(Activator.CreateInstance(typeof(Dictionary <,>).MakeGenericType(gargs [0], gargs [1]))); // Dictionary<T>
                }
                else                                                                                                // non-generic
                {
                    return(new Hashtable());
                }
            }
#if NET_2_1 // FIXME: is it fine?
            return(Activator.CreateInstance(RuntimeType));
#else
            return(Activator.CreateInstance(RuntimeType, true));
#endif
        }
Example #15
0
        //
        // GetConstructor (called by system.RuntimeType.GetConstructorImpl)
        //

        public static ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder,
                                                     CallingConventions callConvention,
                                                     Type[] types, ParameterModifier[] modifiers,
                                                     RuntimeType initialType)
        {
            RuntimeMethodInfo.ValidateGetMethod(binder, callConvention, types, modifiers);

            if (initialType.IsValueType)
            {
                return(null);
            }
            var numGenericArgsInInitialType = initialType.GetGenericArguments().Length;

            RuntimeConstructorInfo foundConstructor = null;

            BindingFlagsIterator.Run(bindingAttr, initialType, MemberTypes.Constructor,
                                     (javaAccessibleObject) =>
            {
                #pragma warning disable 0436
                var javaConstructor = (java.lang.reflect.Constructor)javaAccessibleObject;
                #pragma warning restore 0436

                var constructorTypes = DiscardClasses(initialType.JavaClassForArray(),
                                                      numGenericArgsInInitialType,
                                                      javaConstructor.getParameterTypes(),
                                                      out var hasGenericArgs,
                                                      out var hasUniqueArg);
                if (constructorTypes.Length == 0)
                {
                    javaConstructor.setAccessible(true);
                    foundConstructor = new RuntimeConstructorInfo(javaConstructor, initialType)
                    {
                        HasGenericArgs = hasGenericArgs,
                        HasUniqueArg   = hasUniqueArg,
                    };
                    return(false); // stop iteration
                }

                return(true); // continue iteration
            });
Example #16
0
        public override Type[] GetGenericArguments()
        {
            if (_genericArguments == null)
            {
                var erasedArguments  = RuntimeType.GetGenericArguments();
                var fullArguments    = FullType.GetGenericArguments();
                var genericArguments = new Type[erasedArguments.Length];
                for (int i = 0; i < erasedArguments.Length; i++)
                {
                    var full   = fullArguments[i];
                    var erased = erasedArguments[i];
                    if (full is ErasedWrapperType || full == erased)
                    {
                        genericArguments[i] = full;
                        continue;
                    }

                    genericArguments[i] = new ErasedWrapperType(erased, (InterpretedType)full);
                }
                _genericArguments = genericArguments;
            }

            return(_genericArguments);
        }
Example #17
0
        object CreateInstance()
        {
            if (RuntimeType.IsArray)
            {
                return(new ArrayList());
            }
            if (RuntimeType.IsInterface)
            {
                var icoll = GetGenericCollectionInterface(RuntimeType);
                if (icoll != null)
                {
                    return(Activator.CreateInstance(typeof(List <>).MakeGenericType(RuntimeType.GetGenericArguments() [0]))); // List<T>
                }
                else                                                                                                          // non-generic
                {
                    return(new ArrayList());
                }
            }
#if NET_2_1 // FIXME: is it fine?
            return(Activator.CreateInstance(RuntimeType));
#else
            return(Activator.CreateInstance(RuntimeType, true));
#endif
        }
Example #18
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
        }
Example #19
0
        private protected unsafe void CheckArguments(
            Span <object?> copyOfParameters,
            IntPtr *byrefParameters,
            Span <ParameterCopyBackAction> shouldCopyBack,
            ReadOnlySpan <object?> parameters,
            RuntimeType[] sigTypes,
            Binder?binder,
            CultureInfo?culture,
            BindingFlags invokeAttr
            )
        {
            Debug.Assert(parameters.Length > 0);

            ParameterInfo[]? paramInfos = null;
            for (int i = 0; i < parameters.Length; i++)
            {
                ParameterCopyBackAction copyBackArg = default;
                bool        isValueType             = false;
                object?     arg     = parameters[i];
                RuntimeType sigType = sigTypes[i];

                // Convert a Type.Missing to the default value.
                if (ReferenceEquals(arg, Type.Missing))
                {
                    paramInfos ??= GetParametersNoCopy();
                    ParameterInfo paramInfo = paramInfos[i];

                    if (paramInfo.DefaultValue == DBNull.Value)
                    {
                        throw new ArgumentException(SR.Arg_VarMissNull, nameof(parameters));
                    }

                    arg = paramInfo.DefaultValue;

                    if (sigType.IsNullableOfT)
                    {
                        copyBackArg = ParameterCopyBackAction.CopyNullable;

                        if (arg is not null)
                        {
                            // For nullable Enum types, the ParameterInfo.DefaultValue returns a raw value which
                            // needs to be parsed to the Enum type, for more info: https://github.com/dotnet/runtime/issues/12924
                            Type argumentType = sigType.GetGenericArguments()[0];
                            if (argumentType.IsEnum)
                            {
                                arg = Enum.ToObject(argumentType, arg);
                            }
                        }
                    }
                    else
                    {
                        copyBackArg = ParameterCopyBackAction.Copy;
                    }
                }

                if (arg is null)
                {
                    // Fast path for null reference types.
                    isValueType = RuntimeTypeHandle.IsValueType(sigType);
                    if (isValueType || RuntimeTypeHandle.IsByRef(sigType))
                    {
                        isValueType = sigType.CheckValue(ref arg, ref copyBackArg, binder, culture, invokeAttr);
                    }
                }
                else
                {
                    RuntimeType argType = (RuntimeType)arg.GetType();

                    if (ReferenceEquals(argType, sigType))
                    {
                        // Fast path when the value's type matches the signature type.
                        isValueType = RuntimeTypeHandle.IsValueType(argType);
                    }
                    else if (sigType.TryByRefFastPath(ref arg, ref isValueType))
                    {
                        // Fast path when the value's type matches the signature type of a byref parameter.
                        copyBackArg = ParameterCopyBackAction.Copy;
                    }
                    else
                    {
                        // Slow path that supports type conversions.
                        isValueType = sigType.CheckValue(ref arg, ref copyBackArg, binder, culture, invokeAttr);
                    }
                }

                // We need to perform type safety validation against the incoming arguments, but we also need
                // to be resilient against the possibility that some other thread (or even the binder itself!)
                // may mutate the array after we've validated the arguments but before we've properly invoked
                // the method. The solution is to copy the arguments to a different, not-user-visible buffer
                // as we validate them. n.b. This disallows use of ArrayPool, as ArrayPool-rented arrays are
                // considered user-visible to threads which may still be holding on to returned instances.
                // This separate array is also used to hold default values when 'null' is specified for value
                // types, and also used to hold the results from conversions such as from Int16 to Int32. For
                // compat, these default values and conversions are not be applied to the incoming arguments.
                shouldCopyBack[i]   = copyBackArg;
                copyOfParameters[i] = arg;

                if (isValueType)
                {
#if !MONO // Temporary until Mono is updated.
                    Debug.Assert(arg != null);
                    Debug.Assert(
                        arg.GetType() == sigType ||
                        (sigType.IsPointer && (arg.GetType() == typeof(IntPtr) || arg.GetType() == typeof(UIntPtr))) ||
                        (sigType.IsByRef && arg.GetType() == RuntimeTypeHandle.GetElementType(sigType)) ||
                        ((sigType.IsEnum || arg.GetType().IsEnum) && RuntimeType.GetUnderlyingType((RuntimeType)arg.GetType()) == RuntimeType.GetUnderlyingType(sigType)));
#endif
                    ByReference valueTypeRef = ByReference.Create(ref copyOfParameters[i] !.GetRawData());
                    *(ByReference *)(byrefParameters + i) = valueTypeRef;
                }
                else
                {
                    ByReference objRef = ByReference.Create(ref copyOfParameters[i]);
                    *(ByReference *)(byrefParameters + i) = objRef;
                }
            }
        }
        [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>());
        }