4

假设我有一个带有底层数据存储库的搜索模块,并且要求从搜索查询中返回最多 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;
}

然而,这似乎比必要的有点笨拙。

4

2 回答 2

9

你的方法是最好的方法。我根本不会做任何改变。

如果您的项目少于 26 个,则任何其他选项(例如首先单独查询计数)都会执行两次看似昂贵的操作(进行实际搜索)。在错误情况下您只节省了一点点,而在常见情况下增加了一笔可观的费用。

您的代码唯一不太理想的情况是,如果_repository.Search(name)返回的类型可以廉价地迭代两次并且可以廉价地提供它的计数(例如 a List),但在上下文中似乎并非如此。

于 2013-07-02T19:34:04.947 回答
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;
        }
    }
}
于 2013-07-02T19:53:33.977 回答