From b7a5924b25699ae275fed677ac0a279ebeede283 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 13 Oct 2017 13:38:52 +0200 Subject: [PATCH] When possible, use implicit method group conversions to construct delegates. --- .../TestCases/Pretty/DelegateConstruction.cs | 6 +++--- ICSharpCode.Decompiler/CSharp/CallBuilder.cs | 15 +++++++++------ .../CSharp/TranslatedExpression.cs | 11 +++++++---- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs index cd9681ddc..d4033768b 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs @@ -88,17 +88,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static Action ExtensionMethodUnbound() { - return new Action(DelegateConstruction.Test); + return DelegateConstruction.Test; } public static Action ExtensionMethodBound() { - return new Action("abc".Test); + return "abc".Test; } public static Action ExtensionMethodBoundOnNull() { - return new Action(((string)null).Test); + return ((string)null).Test; } public static object StaticMethod() diff --git a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs index 2a57d77e7..23f0add1a 100644 --- a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs @@ -339,18 +339,21 @@ namespace ICSharpCode.Decompiler.CSharp } var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly); var or = new OverloadResolution(resolver.Compilation, method.Parameters.SelectArray(p => new TypeResolveResult(p.Type))); - var result = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, true) as MethodGroupResolveResult; + var result = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, false); - if (result == null) { + bool needsCast = true; + if (result is MethodGroupResolveResult mgrr) { + or.AddMethodLists(mgrr.MethodsGroupedByDeclaringType.ToArray()); + needsCast = (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(method, or.BestCandidate, func.OpCode == OpCode.LdVirtFtn)); + } + if (needsCast) { target = target.ConvertTo(targetType, expressionBuilder); - } else { - or.AddMethodLists(result.MethodsGroupedByDeclaringType.ToArray()); - if (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(method, or.BestCandidate, func.OpCode == OpCode.LdVirtFtn)) - target = target.ConvertTo(targetType, expressionBuilder); + result = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, false); } var mre = new MemberReferenceExpression(target, method.Name); mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType)); + mre.WithRR(result); var oce = new ObjectCreateExpression(expressionBuilder.ConvertType(inst.Method.DeclaringType), mre) .WithILInstruction(inst) .WithRR(new ConversionResolveResult( diff --git a/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs b/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs index a4f9f2bdd..ad82d776f 100644 --- a/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs @@ -173,11 +173,14 @@ namespace ICSharpCode.Decompiler.CSharp var type = this.Type; if (type.Equals(targetType)) { // Make explicit conversion implicit, if possible - if (allowImplicitConversion && Expression is CastExpression cast && ResolveResult is ConversionResolveResult conversion) { - if (type.IsKnownType(KnownTypeCode.Object) && conversion.Conversion.IsBoxingConversion - || type.Kind == TypeKind.Delegate && conversion.Conversion.IsAnonymousFunctionConversion) - { + if (allowImplicitConversion && ResolveResult is ConversionResolveResult conversion) { + if (Expression is CastExpression cast + && (type.IsKnownType(KnownTypeCode.Object) && conversion.Conversion.IsBoxingConversion + || type.Kind == TypeKind.Delegate && conversion.Conversion.IsAnonymousFunctionConversion + )) { return this.UnwrapChild(cast.Expression); + } else if (Expression is ObjectCreateExpression oce && conversion.Conversion.IsMethodGroupConversion && oce.Arguments.Count == 1) { + return this.UnwrapChild(oce.Arguments.Single()); } } return this;