public static CandidateInfo <T> TypeInference <T>(CandidateInfo <T> candidateInfo, NameResolver resolver) where T : MemberInfo { var method = candidateInfo.Member as MethodInfo; if (method == null || !method.IsGenericMethodDefinition) { throw new InvalidOperationException("Type inference can only be performed on a generic method definition."); } var inferer = new TypeInferer(candidateInfo.Parameters, method, resolver); if (!inferer.infer()) { return(null); } var inferredMethod = method.MakeGenericMethod(inferer._inferred); // Return the list of parameter types with the generic type parameters substituted var parameterTypes = inferredMethod.GetParameters().Select(p => p.ParameterType).ToArray(); // The inferer may have changed an implicit lambda to a LINQ expression, so return the new version of _arguments return(new CandidateInfo <T>((T)(MemberInfo)inferredMethod, candidateInfo.Parameters.Select((p, i) => new CandidateParameterInfo { ParameterType = parameterTypes[i], Mode = p.Mode, Argument = inferer._arguments[i], ArgumentIndex = p.ArgumentIndex, UninstantiatedParameterType = p.ParameterType }).ToArray(), inferredMethod.GetParameters().Length, isLiftedOperator: false, isExpandedForm: candidateInfo.IsExpandedForm)); }
public static CandidateInfo <T> ResolveOverloads <T>(List <Tuple <T, ParameterInfo[]> > overloads, IEnumerable <ArgumentInfo> arguments, NameResolver resolver) where T : MemberInfo { var candidates = overloads.SelectMany(ov => ParserUtil.EvaluateArgumentList(ov.Item1, ov.Item2, arguments, resolver)).ToList(); // Type inference for (int i = 0; i < candidates.Count; i++) { if (candidates[i].Member is MethodInfo && ((MethodInfo)(MemberInfo)candidates[i].Member).IsGenericMethodDefinition) { candidates[i] = TypeInferer.TypeInference(candidates[i], resolver); } } // Remove nulls (entries where type inference failed) and entries that are not applicable (§7.5.3.1 Applicable function member) candidates = candidates.Where(c => c != null && c.Parameters.All(p => p.Mode == ArgumentMode.In ? Conversion.Implicit(p.Argument, p.ParameterType) != null : p.ParameterType == p.Argument.ExpressionType)).ToList(); if (candidates.Count == 0) { return(null); } if (candidates.Count == 1) { return(candidates[0]); } // We have more than one candidate, so need to find the “best” one bool[] cannot = new bool[candidates.Count]; for (int i = 0; i < cannot.Length; i++) { for (int j = i + 1; j < cannot.Length; j++) { int compare = candidates[i].Better(candidates[j]); if (compare != 1) // j is not better { cannot[j] = true; } if (compare != -1) // i is not better { cannot[i] = true; } } } CandidateInfo <T> candidate = null; for (int i = 0; i < cannot.Length; i++) { if (!cannot[i]) { if (candidate == null) { candidate = candidates[i]; } else { // There is more than one applicable candidate — method call is ambiguous return(null); } } } // Either candidate == null, in which case no candidate was better than all others, or this is the successful candidate return(candidate); }