private static void EmitNullableToReferenceConversion(ILGenerator il, Type typeFrom) { Debug.Assert(TypeUtil.IsNullableType(typeFrom)); // We've got a conversion from nullable to Object, ValueType, Enum, etc. Just box it so that // we get the nullable semantics. il.Emit(OpCodes.Box, typeFrom); }
private static void EmitNullableToNonNullableConversion(ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) { Debug.Assert(TypeUtil.IsNullableType(typeFrom)); Debug.Assert(!TypeUtil.IsNullableType(typeTo)); if (typeTo.IsValueType) { EmitNullableToNonNullableStructConversion(il, typeFrom, typeTo, isChecked); } else { EmitNullableToReferenceConversion(il, typeFrom); } }
private static void EmitNullableToNonNullableStructConversion(ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) { Debug.Assert(TypeUtil.IsNullableType(typeFrom)); Debug.Assert(!TypeUtil.IsNullableType(typeTo)); Debug.Assert(typeTo.IsValueType); LocalBuilder locFrom = il.DeclareLocal(typeFrom); il.Emit(OpCodes.Stloc, locFrom); il.Emit(OpCodes.Ldloca, locFrom); EmitGetValue(il, typeFrom); Type nnTypeFrom = TypeUtil.GetNonNullableType(typeFrom); EmitConvertToType(il, nnTypeFrom, typeTo, isChecked); }
private static void EmitNonNullableToNullableConversion(ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) { Debug.Assert(!TypeUtil.IsNullableType(typeFrom)); Debug.Assert(TypeUtil.IsNullableType(typeTo)); LocalBuilder locTo = il.DeclareLocal(typeTo); Type nnTypeTo = TypeUtil.GetNonNullableType(typeTo); EmitConvertToType(il, typeFrom, nnTypeTo, isChecked); ConstructorInfo ci = typeTo.GetConstructor(new[] { nnTypeTo }); il.Emit(OpCodes.Newobj, ci); il.Emit(OpCodes.Stloc, locTo); il.Emit(OpCodes.Ldloc, locTo); }
public static void EmitConvertToType(ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) { if (TypeUtil.AreEquivalent(typeFrom, typeTo)) { return; } if (typeFrom == typeof(void) || typeTo == typeof(void)) { throw new InvalidOperationException(); } bool isTypeFromNullable = TypeUtil.IsNullableType(typeFrom); bool isTypeToNullable = TypeUtil.IsNullableType(typeTo); Type nnExprType = TypeUtil.GetNonNullableType(typeFrom); Type nnType = TypeUtil.GetNonNullableType(typeTo); if (typeFrom.IsInterface || // interface cast typeTo.IsInterface || typeFrom == typeof(object) || // boxing cast typeTo == typeof(object) || typeFrom == typeof(System.Enum) || typeFrom == typeof(System.ValueType) || TypeUtil.IsLegalExplicitVariantDelegateConversion(typeFrom, typeTo)) { EmitCastToType(il, typeFrom, typeTo); } else if (isTypeFromNullable || isTypeToNullable) { EmitNullableConversion(il, typeFrom, typeTo, isChecked); } else if (!(TypeUtil.IsConvertible(typeFrom) && TypeUtil.IsConvertible(typeTo)) // primitive runtime conversion && (nnExprType.IsAssignableFrom(nnType) || // down cast nnType.IsAssignableFrom(nnExprType))) // up cast { EmitCastToType(il, typeFrom, typeTo); } else if (typeFrom.IsArray && typeTo.IsArray) { // See DevDiv Bugs #94657. EmitCastToType(il, typeFrom, typeTo); } else { EmitNumericConversion(il, typeFrom, typeTo, isChecked); } }
private static void EmitNullableConversion(ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) { bool isTypeFromNullable = TypeUtil.IsNullableType(typeFrom); bool isTypeToNullable = TypeUtil.IsNullableType(typeTo); Debug.Assert(isTypeFromNullable || isTypeToNullable); if (isTypeFromNullable && isTypeToNullable) { EmitNullableToNullableConversion(il, typeFrom, typeTo, isChecked); } else if (isTypeFromNullable) { EmitNullableToNonNullableConversion(il, typeFrom, typeTo, isChecked); } else { EmitNonNullableToNullableConversion(il, typeFrom, typeTo, isChecked); } }
private static void EmitNullableToNullableConversion(ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) { Debug.Assert(TypeUtil.IsNullableType(typeFrom)); Debug.Assert(TypeUtil.IsNullableType(typeTo)); LocalBuilder locFrom = il.DeclareLocal(typeFrom); il.Emit(OpCodes.Stloc, locFrom); LocalBuilder locTo = il.DeclareLocal(typeTo); // test for null il.Emit(OpCodes.Ldloca, locFrom); EmitHasValue(il, typeFrom); Label labIfNull = il.DefineLabel(); il.Emit(OpCodes.Brfalse_S, labIfNull); il.Emit(OpCodes.Ldloca, locFrom); EmitGetValueOrDefault(il, typeFrom); Type nnTypeFrom = TypeUtil.GetNonNullableType(typeFrom); Type nnTypeTo = TypeUtil.GetNonNullableType(typeTo); EmitConvertToType(il, nnTypeFrom, nnTypeTo, isChecked); // construct result type ConstructorInfo ci = typeTo.GetConstructor(new[] { nnTypeTo }); il.Emit(OpCodes.Newobj, ci); il.Emit(OpCodes.Stloc, locTo); Label labEnd = il.DefineLabel(); il.Emit(OpCodes.Br_S, labEnd); // if null then create a default one il.MarkLabel(labIfNull); il.Emit(OpCodes.Ldloca, locTo); il.Emit(OpCodes.Initobj, typeTo); il.MarkLabel(labEnd); il.Emit(OpCodes.Ldloc, locTo); }