diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpConversions.cs b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpConversions.cs
index d75e4de3f0..8e6e92248f 100644
--- a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpConversions.cs
+++ b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpConversions.cs
@@ -921,7 +921,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
args[i] = new ResolveResult(parameterType);
}
}
- var or = rr.PerformOverloadResolution(compilation, args, allowExpandingParams: false, conversions: this);
+ var or = rr.PerformOverloadResolution(compilation, args, allowExpandingParams: false, allowOptionalParameters: false, conversions: this);
if (or.FoundApplicableCandidate) {
IMethod method = (IMethod)or.GetBestCandidateWithSubstitutedTypeArguments();
var thisRR = rr.TargetResult as ThisResolveResult;
diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs b/ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs
index 39571f2918..fddfda7c5a 100644
--- a/ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs
+++ b/ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs
@@ -220,7 +220,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return string.Format("[{0} with {1} method(s)]", GetType().Name, this.Methods.Count());
}
- public OverloadResolution PerformOverloadResolution(ICompilation compilation, ResolveResult[] arguments, string[] argumentNames = null, bool allowExtensionMethods = true, bool allowExpandingParams = true, bool checkForOverflow = false, CSharpConversions conversions = null)
+ public OverloadResolution PerformOverloadResolution(ICompilation compilation, ResolveResult[] arguments, string[] argumentNames = null,
+ bool allowExtensionMethods = true,
+ bool allowExpandingParams = true,
+ bool allowOptionalParameters = true,
+ bool checkForOverflow = false, CSharpConversions conversions = null)
{
Log.WriteLine("Performing overload resolution for " + this);
Log.WriteCollection(" Arguments: ", arguments);
@@ -228,6 +232,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
var typeArgumentArray = this.TypeArguments.ToArray();
OverloadResolution or = new OverloadResolution(compilation, arguments, argumentNames, typeArgumentArray, conversions);
or.AllowExpandingParams = allowExpandingParams;
+ or.AllowOptionalParameters = allowOptionalParameters;
or.CheckForOverflow = checkForOverflow;
or.AddMethodLists(methodLists);
@@ -249,6 +254,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
var extOr = new OverloadResolution(compilation, extArguments, extArgumentNames, typeArgumentArray, conversions);
extOr.AllowExpandingParams = allowExpandingParams;
+ extOr.AllowOptionalParameters = allowOptionalParameters;
extOr.IsExtensionMethodInvocation = true;
extOr.CheckForOverflow = checkForOverflow;
diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs b/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs
index ce1ce09570..6c4e814f20 100644
--- a/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs
+++ b/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs
@@ -155,6 +155,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
this.conversions = conversions ?? CSharpConversions.Get(compilation);
this.AllowExpandingParams = true;
+ this.AllowOptionalParameters = true;
}
#endregion
@@ -174,6 +175,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
///
public bool AllowExpandingParams { get; set; }
+ ///
+ /// Gets/Sets whether optional parameters may be left at their default value.
+ /// The default value is true.
+ /// If this property is set to false, optional parameters will be treated like regular parameters.
+ ///
+ public bool AllowOptionalParameters { get; set; }
+
///
/// Gets/Sets whether ConversionResolveResults created by this OverloadResolution
/// instance apply overflow checking.
@@ -543,7 +551,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (candidate.IsExpandedForm && i == argumentCountPerParameter.Length - 1)
continue; // any number of arguments is fine for the params-array
if (argumentCountPerParameter[i] == 0) {
- if (candidate.Parameters[i].IsOptional)
+ if (this.AllowOptionalParameters && candidate.Parameters[i].IsOptional)
candidate.HasUnmappedOptionalParameters = true;
else
candidate.AddError(OverloadResolutionErrors.MissingArgumentForRequiredParameter);
diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
index 4776a5185d..d9a3438a25 100644
--- a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
+++ b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
@@ -1583,7 +1583,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
var addRR = memberLookup.Lookup(initializedObject, "Add", EmptyList.Instance, true);
var mgrr = addRR as MethodGroupResolveResult;
if (mgrr != null) {
- OverloadResolution or = mgrr.PerformOverloadResolution(resolver.Compilation, addArguments, null, false, false, resolver.CheckForOverflow, resolver.conversions);
+ OverloadResolution or = mgrr.PerformOverloadResolution(resolver.Compilation, addArguments, null, false, false, false, resolver.CheckForOverflow, resolver.conversions);
var invocationRR = or.CreateResolveResult(initializedObject);
StoreResult(aie, invocationRR);
ProcessInvocationResult(null, aie.Elements, invocationRR);
@@ -2745,7 +2745,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} else {
var getEnumeratorMethodGroup = memberLookup.Lookup(expression, "GetEnumerator", EmptyList.Instance, true) as MethodGroupResolveResult;
if (getEnumeratorMethodGroup != null) {
- var or = getEnumeratorMethodGroup.PerformOverloadResolution(compilation, new ResolveResult[0]);
+ var or = getEnumeratorMethodGroup.PerformOverloadResolution(
+ compilation, new ResolveResult[0],
+ allowExtensionMethods: false, allowExpandingParams: false, allowOptionalParameters: false);
if (or.FoundApplicableCandidate && !or.IsAmbiguous && !or.BestCandidate.IsStatic && or.BestCandidate.IsPublic) {
collectionType = expression.Type;
getEnumeratorInvocation = or.CreateResolveResult(expression);
@@ -2762,7 +2764,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
IMethod moveNextMethod = null;
var moveNextMethodGroup = memberLookup.Lookup(new ResolveResult(enumeratorType), "MoveNext", EmptyList.Instance, false) as MethodGroupResolveResult;
if (moveNextMethodGroup != null) {
- var or = moveNextMethodGroup.PerformOverloadResolution(compilation, new ResolveResult[0]);
+ var or = moveNextMethodGroup.PerformOverloadResolution(
+ compilation, new ResolveResult[0],
+ allowExtensionMethods: false, allowExpandingParams: false, allowOptionalParameters: false);
moveNextMethod = or.GetBestCandidateWithSubstitutedTypeArguments() as IMethod;
}
diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs b/ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs
index e082f98d8e..6438b82856 100644
--- a/ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs
+++ b/ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs
@@ -510,7 +510,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
var or = mgrr.PerformOverloadResolution(compilation,
args,
- allowExpandingParams: false);
+ allowExpandingParams: false, allowOptionalParameters: false);
if (or.FoundApplicableCandidate && or.BestCandidateAmbiguousWith == null) {
IType returnType = or.GetBestCandidateWithSubstitutedTypeArguments().ReturnType;
MakeLowerBoundInference(returnType, m.ReturnType);
diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs
index 3087c1cd3a..836d9c2526 100644
--- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs
+++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs
@@ -19,6 +19,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Linq;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
@@ -782,5 +783,53 @@ class Test {
//Assert.IsFrue(c.IsValid);
Assert.IsTrue(c.IsMethodGroupConversion);
}
+
+ [Test]
+ public void MethodGroupConversion_ExactMatchIsBetter()
+ {
+ string program = @"using System;
+class Test {
+ delegate void D(string a);
+ D d = $M$;
+ static void M(object x) {}
+ static void M(string x = null) {}
+}";
+ var c = GetConversion(program);
+ Assert.IsTrue(c.IsValid);
+ Assert.IsTrue(c.IsMethodGroupConversion);
+ Assert.AreEqual("System.String", c.Method.Parameters.Single().Type.FullName);
+ }
+
+ [Test]
+ public void MethodGroupConversion_CannotLeaveOutOptionalParameters()
+ {
+ string program = @"using System;
+class Test {
+ delegate void D(string a);
+ D d = $M$;
+ static void M(object x) {}
+ static void M(string x, string y = null) {}
+}";
+ var c = GetConversion(program);
+ Assert.IsTrue(c.IsValid);
+ Assert.IsTrue(c.IsMethodGroupConversion);
+ Assert.AreEqual("System.Object", c.Method.Parameters.Single().Type.FullName);
+ }
+
+ [Test]
+ public void MethodGroupConversion_CannotUseExpandedParams()
+ {
+ string program = @"using System;
+class Test {
+ delegate void D(string a);
+ D d = $M$;
+ static void M(object x) {}
+ static void M(params string[] x) {}
+}";
+ var c = GetConversion(program);
+ Assert.IsTrue(c.IsValid);
+ Assert.IsTrue(c.IsMethodGroupConversion);
+ Assert.AreEqual("System.Object", c.Method.Parameters.Single().Type.FullName);
+ }
}
}