diff --git a/src/Microsoft.OData.Edm/Csdl/Semantics/CsdlSemanticsVocabularyAnnotation.cs b/src/Microsoft.OData.Edm/Csdl/Semantics/CsdlSemanticsVocabularyAnnotation.cs index 6431b7078b..39118ec384 100644 --- a/src/Microsoft.OData.Edm/Csdl/Semantics/CsdlSemanticsVocabularyAnnotation.cs +++ b/src/Microsoft.OData.Edm/Csdl/Semantics/CsdlSemanticsVocabularyAnnotation.cs @@ -456,19 +456,18 @@ private IEdmVocabularyAnnotatable ComputeTarget() private static IEdmOperationImport FindParameterizedOperationImport(string parameterizedName, Func> findFunctions, Func, IEdmOperationImport> ambiguityCreator) { IEnumerable matchingFunctions = findFunctions(parameterizedName); - if (!matchingFunctions.Any()) + var length = TryCount(matchingFunctions, out var value); + if (length == 0) { return null; } - - if (matchingFunctions.Count() == 1) + else if (length == 1) { - return matchingFunctions.First(); + return value; } else { - IEdmOperationImport ambiguous = ambiguityCreator(matchingFunctions); - return ambiguous; + return ambiguityCreator(matchingFunctions); } } @@ -484,19 +483,18 @@ private IEdmOperation FindParameterizedOperation(string parameterizedName, Func< string name = parameterizedName.Substring(0, openParen); string[] parameters = parameterizedName.Substring(openParen + 1, closeParen - (openParen + 1)).Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries); IEnumerable matchingFunctions = this.FindParameterizedOperationFromList(findFunctions(name).Cast(), parameters); - if (!matchingFunctions.Any()) + var length = TryCount(matchingFunctions, out var value); + if (length == 0) { return null; } - - if (matchingFunctions.Count() == 1) + else if (length == 1) { - return matchingFunctions.First(); + return value; } else { - IEdmOperation ambiguous = ambiguityCreator(matchingFunctions); - return ambiguous; + return ambiguityCreator(matchingFunctions); } } @@ -577,5 +575,31 @@ private IEnumerable FindParameterizedOperationFromList(IEnumerabl return matchingOperations; } + + private static int TryCount(IEnumerable source, out T value) + { + //// TODO check build from https://github.com/OData/odata.net/pull/2237 + //// TODO benchmark this + //// TODO ensure that there are existing tests covering this + //// TODO add prepend stuff so that you are sure to enumerate only once? + using (var enumerator = source.GetEnumerator()) + { + int length; + for (length = 0; length < 2 && enumerator.MoveNext(); ++length) + { + } + + if (length == 1) + { + value = enumerator.Current; + } + else + { + value = default(T); + } + + return length; + } + } } }