/// <summary>Finds the best methods for the specified arguments given a candidate method enumeration.</summary> /// <param name="signatures">The candidate function signatures.</param> /// <param name="argumentTypes">The argument type references to match.</param> /// <returns>The number of "best match" methods.</returns> private static int FindBestSignature(FunctionSignature[] signatures, IEdmTypeReference[] argumentTypes) { Debug.Assert(signatures != null, "signatures != null"); Debug.Assert(argumentTypes != null, "argumentTypes != null"); Debug.Assert(argumentTypes.All(t => t == null || t.IsODataPrimitiveTypeKind()), "All argument types must be primitive or null."); Debug.Assert(signatures.All(s => s.ArgumentTypes != null && s.ArgumentTypes.All(t => t.IsODataPrimitiveTypeKind())), "All signatures must have only primitive argument types."); List<FunctionSignature> applicableSignatures = signatures.Where(signature => IsApplicable(signature, argumentTypes)).ToList(); if (applicableSignatures.Count > 1) { applicableSignatures = FindBestApplicableSignatures(applicableSignatures, argumentTypes); } int result = applicableSignatures.Count; if (result == 1) { // TODO: deal with the situation that we started off with all non-open types // and end up with all open types; see RequestQueryParser.FindBestMethod. // Ignored for now since we don't support open types yet. FunctionSignature signature = applicableSignatures[0]; for (int i = 0; i < argumentTypes.Length; i++) { argumentTypes[i] = signature.ArgumentTypes[i]; } result = 1; } else if (result > 1) { // We may have the case for operators (which C# doesn't) in which we have a nullable operand // and a non-nullable operand. We choose to convert the one non-null operand to nullable in that // case (the binary expression will lift to null). if (argumentTypes.Length == 2 && result == 2) { if (applicableSignatures[0].ArgumentTypes[0].Definition.IsEquivalentTo(applicableSignatures[1].ArgumentTypes[0].Definition)) { FunctionSignature nullableMethod = applicableSignatures[0].ArgumentTypes[0].IsNullable ? applicableSignatures[0] : applicableSignatures[1]; argumentTypes[0] = nullableMethod.ArgumentTypes[0]; argumentTypes[1] = nullableMethod.ArgumentTypes[1]; // TODO: why is this necessary? We keep it here for now since the product has it but assert // that nothing new was found. int signatureCount = FindBestSignature(signatures, argumentTypes); Debug.Assert(signatureCount == 1, "signatureCount == 1"); Debug.Assert(argumentTypes[0] == nullableMethod.ArgumentTypes[0], "argumentTypes[0] == nullableMethod.ArgumentTypes[0]"); Debug.Assert(argumentTypes[1] == nullableMethod.ArgumentTypes[1], "argumentTypes[1] == nullableMethod.ArgumentTypes[1]"); return signatureCount; } } } return result; }