/// <summary> /// Gets which function member is better. (§ 14.4.2.2) /// </summary> /// <returns>0 if neither method is better. 1 if c1 is better. 2 if c2 is better.</returns> int GetBetterFunctionMember(Candidate c1, Candidate c2) { int length = Math.Min(Math.Min(c1.Parameters.Count, c2.Parameters.Count), arguments.Count); bool foundBetterParamIn1 = false; bool foundBetterParamIn2 = false; for (int i = 0; i < length; i++) { if (arguments[i] == null) { continue; } int res = MemberLookupHelper.GetBetterConversion(arguments[i], c1.Parameters[i].ReturnType, c2.Parameters[i].ReturnType); if (res == 1) { foundBetterParamIn1 = true; } if (res == 2) { foundBetterParamIn2 = true; } } if (foundBetterParamIn1 && !foundBetterParamIn2) { return(1); } if (foundBetterParamIn2 && !foundBetterParamIn1) { return(2); } if (foundBetterParamIn1 && foundBetterParamIn2) { return(0); // ambigous } // If none conversion is better than any other, it is possible that the // expanded parameter lists are the same: for (int i = 0; i < length; i++) { if (!object.Equals(c1.Parameters[i].ReturnType, c2.Parameters[i].ReturnType)) { // if expanded parameters are not the same, neither function member is better return(0); } } // the expanded parameters are the same, apply the tie-breaking rules from the spec: // if one method is generic and the other non-generic, the non-generic is better bool m1IsGeneric = c1.TypeParameterCount > 0; bool m2IsGeneric = c2.TypeParameterCount > 0; if (m1IsGeneric && !m2IsGeneric) { return(2); } if (m2IsGeneric && !m1IsGeneric) { return(1); } // for params parameters: non-expanded calls are better if (c1.IsExpanded && !c2.IsExpanded) { return(2); } if (c2.IsExpanded && !c1.IsExpanded) { return(1); } // if the number of parameters is different, the one with more parameters is better // this occurs when only when both methods are expanded if (c1.OriginalMethod.Parameters.Count > c2.OriginalMethod.Parameters.Count) { return(1); } if (c2.OriginalMethod.Parameters.Count > c1.OriginalMethod.Parameters.Count) { return(2); } IReturnType[] m1ParamTypes = new IReturnType[c1.Parameters.Count]; IReturnType[] m2ParamTypes = new IReturnType[c2.Parameters.Count]; for (int i = 0; i < m1ParamTypes.Length; i++) { m1ParamTypes[i] = c1.Parameters[i].ReturnType; m2ParamTypes[i] = c2.Parameters[i].ReturnType; } return(GetMoreSpecific(m1ParamTypes, m2ParamTypes)); }