private static void EmitNullableToNullableConversion(this ILGenerator ilGenerator, Type typeFrom, Type typeTo, bool isChecked) { Label labIfNull = default(Label); Label labEnd = default(Label); LocalBuilder locFrom = null; LocalBuilder locTo = null; locFrom = ilGenerator.DeclareLocal(typeFrom); ilGenerator.Emit(OpCodes.Stloc, locFrom); locTo = ilGenerator.DeclareLocal(typeTo); // test for null ilGenerator.Emit(OpCodes.Ldloca, locFrom); ilGenerator.EmitHasValue(typeFrom); labIfNull = ilGenerator.DefineLabel(); ilGenerator.Emit(OpCodes.Brfalse_S, labIfNull); ilGenerator.Emit(OpCodes.Ldloca, locFrom); ilGenerator.EmitGetValueOrDefault(typeFrom); Type nnTypeFrom = TypeInfoUtils.GetNonNullableType(typeFrom); Type nnTypeTo = TypeInfoUtils.GetNonNullableType(typeTo); ilGenerator.EmitConvertToType(nnTypeFrom, nnTypeTo, isChecked); // construct result type ConstructorInfo ci = typeTo.GetConstructor(new Type[] { nnTypeTo }); ilGenerator.Emit(OpCodes.Newobj, ci); ilGenerator.Emit(OpCodes.Stloc, locTo); labEnd = ilGenerator.DefineLabel(); ilGenerator.Emit(OpCodes.Br_S, labEnd); // if null then create a default one ilGenerator.MarkLabel(labIfNull); ilGenerator.Emit(OpCodes.Ldloca, locTo); ilGenerator.Emit(OpCodes.Initobj, typeTo); ilGenerator.MarkLabel(labEnd); ilGenerator.Emit(OpCodes.Ldloc, locTo); }
private static void EmitNullableToNonNullableStructConversion(this ILGenerator ilGenerator, Type typeFrom, Type typeTo, bool isChecked) { LocalBuilder locFrom = null; locFrom = ilGenerator.DeclareLocal(typeFrom); ilGenerator.Emit(OpCodes.Stloc, locFrom); ilGenerator.Emit(OpCodes.Ldloca, locFrom); ilGenerator.EmitGetValue(typeFrom); Type nnTypeFrom = TypeInfoUtils.GetNonNullableType(typeFrom); ilGenerator.EmitConvertToType(nnTypeFrom, typeTo, isChecked); }
internal static bool HasReferenceConversion(Type source, Type dest) { // void -> void conversion is handled elsewhere // (it's an identity conversion) // All other void conversions are disallowed. if (source == typeof(void) || dest == typeof(void)) { return(false); } var nnSourceType = TypeInfoUtils.GetNonNullableType(source).GetTypeInfo(); var nnDestType = TypeInfoUtils.GetNonNullableType(dest).GetTypeInfo(); // Down conversion if (nnSourceType.IsAssignableFrom(nnDestType)) { return(true); } // Up conversion if (nnDestType.IsAssignableFrom(nnSourceType)) { return(true); } // Interface conversion if (source.IsInterface || dest.IsInterface) { return(true); } // Variant delegate conversion if (IsLegalExplicitVariantDelegateConversion(source, dest)) { return(true); } // Object conversion if (source == typeof(object) || dest == typeof(object)) { return(true); } return(false); }