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 nnExprType = typeFrom.Unwrap(); var nnType = typeTo.Unwrap(); if (nnType == nnExprType || nnType.IsEquivalentTo(nnExprType)) { return; } if (typeFrom.IsInterface || // interface cast typeTo.IsInterface || typeFrom == typeof(object) || // boxing cast typeTo == typeof(object) || typeFrom == typeof(Enum) || typeFrom == typeof(ValueType) || TypeInfoUtils.IsLegalExplicitVariantDelegateConversion(typeFrom, typeTo)) { ilGenerator.EmitCastToType(typeFrom, typeTo); } else if (typeFrom.IsNullableType() || typeTo.IsNullableType()) { ilGenerator.EmitNullableConversion(typeFrom, typeTo, isChecked); } else if (!(typeFrom.IsConvertible() && typeTo.IsConvertible()) // primitive runtime conversion && (nnExprType.GetTypeInfo().IsAssignableFrom(nnType) || // down cast nnType.GetTypeInfo().IsAssignableFrom(nnExprType))) // up cast { ilGenerator.EmitCastToType(typeFrom, typeTo); } else if (typeFrom.IsArray && typeTo.IsArray) { // See DevDiv Bugs #94657. ilGenerator.EmitCastToType(typeFrom, typeTo); } else { ilGenerator.EmitNumericConversion(typeFrom, typeTo, isChecked); } }