diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs index 8ffb4385a..4db21b12e 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs @@ -836,12 +836,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void AsTypeExpr() { Test>((object obj) => obj as MyClass, (object obj) => obj as MyClass); + Test>((object obj) => obj as int?, (object obj) => obj as int?); Test>>((object obj) => obj as GenericClass, (object obj) => obj as GenericClass); } public static void IsTypeExpr() { Test>((object obj) => obj is MyClass, (object obj) => obj is MyClass); + Test>((object obj) => obj is int?, (object obj) => obj is int?); } public static void UnaryLogicalOperators() diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs index 6f8b63741..b3ca0ef00 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs @@ -995,9 +995,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms var converted = ConvertInstruction(invocation.Arguments[0]).Item1; if (!MatchGetTypeFromHandle(invocation.Arguments[1], out var type)) return (null, SpecialType.UnknownType); - if (converted != null) - return (new IsInst(converted, type), type); - return (null, SpecialType.UnknownType); + if (converted == null) + return (null, SpecialType.UnknownType); + + ILInstruction inst = new IsInst(converted, type); + // We must follow ECMA-335, III.4.6: + // If typeTok is a nullable type, Nullable, it is interpreted as "boxed" T. + if (type.IsKnownType(KnownTypeCode.NullableOfT)) + inst = new UnboxAny(inst, type); + return (inst, type); } (ILInstruction, IType) ConvertTypeIs(CallInstruction invocation)