diff --git a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs index 580a42214..eacc1c9c3 100644 --- a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs @@ -447,7 +447,12 @@ namespace ICSharpCode.Decompiler.Ast case ILCode.Conv_Ovf_I_Un: return arg1.CastTo(typeof(IntPtr)); case ILCode.Conv_Ovf_U_Un: return arg1.CastTo(typeof(UIntPtr)); case ILCode.Castclass: return arg1.CastTo(operandAsTypeRef); - case ILCode.Unbox_Any: return arg1.CastTo(operandAsTypeRef); + case ILCode.Unbox_Any: + // unboxing does not require a cast if the argument was an isinst instruction + if (arg1 is AsExpression && byteCode.Arguments[0].Code == ILCode.Isinst && TypeAnalysis.IsSameType(operand as TypeReference, byteCode.Arguments[0].Operand as TypeReference)) + return arg1; + else + return arg1.CastTo(operandAsTypeRef); case ILCode.Isinst: return arg1.CastAs(operandAsTypeRef); case ILCode.Box: return arg1; case ILCode.Unbox: return InlineAssembly(byteCode, args); diff --git a/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs index 6992a907b..754931197 100644 --- a/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs +++ b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs @@ -648,9 +648,15 @@ namespace ICSharpCode.Decompiler.ILAst case ILCode.Conv_R_Un: return (expectedType != null && expectedType.MetadataType == MetadataType.Single) ? typeSystem.Single : typeSystem.Double; case ILCode.Castclass: - case ILCode.Isinst: case ILCode.Unbox_Any: return (TypeReference)expr.Operand; + case ILCode.Isinst: + { + // isinst performs the equivalent of a cast only for reference types; + // value types still need to be unboxed after an isinst instruction + TypeReference tr = (TypeReference)expr.Operand; + return tr.IsValueType ? typeSystem.Object : tr; + } case ILCode.Box: if (forceInferChildren) InferTypeForExpression(expr.Arguments.Single(), (TypeReference)expr.Operand); diff --git a/ICSharpCode.Decompiler/Tests/ValueTypes.cs b/ICSharpCode.Decompiler/Tests/ValueTypes.cs index 11f2f76f8..5bb93642e 100644 --- a/ICSharpCode.Decompiler/Tests/ValueTypes.cs +++ b/ICSharpCode.Decompiler/Tests/ValueTypes.cs @@ -111,4 +111,19 @@ public static class ValueTypes { ValueTypes.MakeArray()[Environment.TickCount]++; } + + public static bool Is(object obj) + { + return obj is ValueTypes.S; + } + + public static bool IsNullable(object obj) + { + return obj is ValueTypes.S?; + } + + public static ValueTypes.S? As(object obj) + { + return obj as ValueTypes.S?; + } }