假设我有一个带有底层数据存储库的搜索模块,并且要求从搜索查询中返回最多25个结果。我可以使用Take()操作强制执行此操作:
IEnumerable<Contact> Search(string name)
{
// validation/cleanup on name parameter
IEnumerable<Contact> matching = _repository.Search(name);
return matching.Take(25);
}
接下来,假设如果返回的结果超过25个(即搜索参数太宽),我还需要抛出异常。使用LINQ有一种直接的方法吗?到目前为止,我最接近的是取一个多于最大数量并使用它:
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;
}
然而,这似乎有点笨拙。
答案 0 :(得分:9)
您的方法是最好的方法。我根本不会做任何改变。
任何其他选项,例如首先单独查询计数,如果您的项目少于26项,则执行看似昂贵的操作(进行实际搜索)两次。在错误情况下只保留一点点,并在常见情况下增加了大量费用。
唯一一次你的代码不那么令人满意的是,如果_repository.Search(name)
返回的类型可以廉价地迭代两次并且可以便宜地提供它的计数(比如说,List
)但是在上下文中似乎并非如此。
答案 1 :(得分:0)
您可以创建自己的通用迭代器块扩展方法,并将其用于任何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;
}
}
}