public void EmitConvert(Type from, Type to, bool check = false) { if (from == to) { return; } if (!from.IsValueType) { if (!to.IsValueType) { Il.Castclass(to); } else { if (from != typeof(object) && !(from == typeof(Enum) && to.IsEnum)) { throw new InvalidCastException("Cannot cast an object of type '" + from + "' to type '" + to + "'"); } Il.Unbox_Any(to); } } else { if (!to.IsValueType) { if (to != typeof(object) && !(to == typeof(Enum) && from.IsEnum)) { throw new InvalidCastException("Cannot cast an object of type '" + from + "' to type '" + to + "'"); } Il.Box(from); } else { if (to.IsNullable()) { var toArgument = to.GetGenericArguments()[0]; if (from.IsNullable()) { var fromArgument = from.GetGenericArguments()[0]; using (var temp = DeclareLocal(from)) { Il.Stloc(temp); Il.Ldloca(temp); EmitHasValueAccess(from); var valueIsNullLabel = Il.DefineLabel("valueIsNull"); Il.Brfalse(valueIsNullLabel); Il.Ldloca(temp); EmitValueAccess(from); if (toArgument != fromArgument) { EmitConvert(fromArgument, toArgument, check); } Il.Newobj(to.GetConstructor(new[] { toArgument })); var doneLabel = Il.DefineLabel("done"); Il.Br(doneLabel); MarkLabelAndSurroundWithSP(valueIsNullLabel); EmitLoadDefaultValue(to); MarkLabelAndSurroundWithSP(doneLabel); } } else { if (toArgument != from) { EmitConvert(from, toArgument, check); } Il.Newobj(to.GetConstructor(new[] { toArgument })); } } else if (from.IsNullable()) { var fromArgument = from.GetGenericArguments()[0]; using (var temp = DeclareLocal(from)) { Il.Stloc(temp); Il.Ldloca(temp); var valueIsNullLabel = Il.DefineLabel("valueIsNull"); Il.Brfalse(valueIsNullLabel); Il.Ldloca(temp); EmitValueAccess(from); if (to != fromArgument) { EmitConvert(fromArgument, to, check); } var doneLabel = Il.DefineLabel("done"); Il.Br(doneLabel); MarkLabelAndSurroundWithSP(valueIsNullLabel); EmitLoadDefaultValue(to); MarkLabelAndSurroundWithSP(doneLabel); } } else if (to.IsEnum || to == typeof(Enum)) { EmitConvert(from, typeof(int), check); } else if (from.IsEnum || from == typeof(Enum)) { EmitConvert(typeof(int), to, check); } else { if (!check) { EmitConvertValue(Il, from, to); } else { EmitConvertValueChecked(Il, from, to); } } } } }