public static void EmitConvertToType(this ILGenerator ilGenerator, Type typeFrom, Type typeTo, bool isChecked = true) { if (ilGenerator == null) { throw new ArgumentNullException(nameof(ilGenerator)); } if (typeFrom == null) { throw new ArgumentNullException(nameof(typeFrom)); } if (typeTo == null) { throw new ArgumentNullException(nameof(typeTo)); } var typeFromInfo = typeFrom.GetTypeInfo(); var typeToInfo = typeTo.GetTypeInfo(); var nnExprType = typeFromInfo.GetNonNullableType(); var nnType = typeToInfo.GetNonNullableType(); if (TypeExtensions.AreEquivalent(typeFromInfo, typeToInfo)) { return; } if (typeFromInfo.IsInterface || // interface cast typeToInfo.IsInterface || typeFrom == typeof(object) || // boxing cast typeTo == typeof(object) || typeFrom == typeof(System.Enum) || typeFrom == typeof(System.ValueType) || TypeExtensions.IsLegalExplicitVariantDelegateConversion(typeFromInfo, typeToInfo)) { ilGenerator.EmitCastToType(typeFromInfo, typeToInfo); } else if (typeFromInfo.IsNullableType() || typeToInfo.IsNullableType()) { ilGenerator.EmitNullableConversion(typeFromInfo, typeToInfo, isChecked); } else if (!(typeFromInfo.IsConvertible() && typeToInfo.IsConvertible()) // primitive runtime conversion && (nnExprType.GetTypeInfo().IsAssignableFrom(nnType) || // down cast nnType.GetTypeInfo().IsAssignableFrom(nnExprType))) // up cast { ilGenerator.EmitCastToType(typeFromInfo, typeToInfo); } else if (typeFromInfo.IsArray && typeToInfo.IsArray) { // See DevDiv Bugs #94657. ilGenerator.EmitCastToType(typeFromInfo, typeToInfo); } else { ilGenerator.EmitNumericConversion(typeFromInfo, typeToInfo, isChecked); } }