Browse Source

When possible, use implicit method group conversions to construct delegates.

pull/909/merge
Daniel Grunwald 8 years ago
parent
commit
b7a5924b25
  1. 6
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs
  2. 15
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  3. 11
      ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

6
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs

@ -88,17 +88,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -88,17 +88,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static Action<string> ExtensionMethodUnbound()
{
return new Action<string>(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()

15
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -339,18 +339,21 @@ namespace ICSharpCode.Decompiler.CSharp @@ -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(

11
ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

@ -173,11 +173,14 @@ namespace ICSharpCode.Decompiler.CSharp @@ -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;

Loading…
Cancel
Save