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>()); }
[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 }
[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>()); }
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> ()); }
[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>()); }
// // 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 }
[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>()); }
/// <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>()); }
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>()); }
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>()); }
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 }
// // 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 });
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); }
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 }
[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 }
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>()); }