Reputation: 2344
Suppose I have a search module with an underlying data repository, and a requirement to return a maximum of 25 results from the search query. I can enforce this with a Take() operation:
IEnumerable<Contact> Search(string name)
{
// validation/cleanup on name parameter
IEnumerable<Contact> matching = _repository.Search(name);
return matching.Take(25);
}
Next, suppose I have an additional requirement to throw an exception if more than 25 results would be returned (i.e. the search parameter is too broad). Is there a straightforward way to do this with LINQ? The closest I have come so far is to take one more than the maximum number and work with that:
IEnumerable<Contact> Search(string name)
{
// validation/cleanup on name parameter
var matching = _repository.Search(name);
var toReturn = matching.Take(26).ToList();
if (toReturn.Count() > 25)
{
throw new Exception("Too many results");
}
return toReturn;
}
However, this seems a bit clunkier than necessary.
Upvotes: 4
Views: 205
Reputation: 63435
You could make your own generic iterator block extension method and use it for any IEnumerable<T>
:
public static class EnumerableExtensions
{
public static IEnumerable<T> TakeWithMaximum<T>(this IEnumerable<T> source, int maxCount)
{
if (source == null)
throw new ArgumentNullException("source");
int count = 0;
foreach (T item in source)
{
if (++count > maxCount)
throw new InvalidOperationException(string.Format("More than the maximum specified number of elements ({0}) were returned.", maxCount));
yield return item;
}
}
}
Upvotes: 0
Reputation: 203817
Your method is the best method. I would not make any changes at all.
Any other option, such as querying the count alone first is performing what appears to be an expensive operation (doing the actual searching) twice in the event that you have less than 26 items. You save only a little tiny bit in the error case and add a significant expense in the common case.
The only time your code would be less desirable is if _repository.Search(name)
returned a type that could be cheaply iterated twice and that could cheaply provide it's count (like, say, a List
) but in context that doesn't appear to be the case.
Upvotes: 9