2013-07-02 23 views
4

假設我有一個帶有基礎數據存儲庫的搜索模塊,並且要求從搜索查詢返回最多25個結果。我可以用取()操作執行此:返回最大數量的項目LINQ方式

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

這哪裏是數字「25」來的?它是作爲參數傳遞的嗎? – Thousand

+0

你可以只檢查'匹配'上的Count()嗎? –

+0

'Single'方法與您的建議類似。 'SELECT TOP 2'並且在返回兩個時拋出一個錯誤。 –

回答

9

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

任何其他選項(例如首先查詢計數)都會在您少於26個項目的情況下執行兩次似乎是昂貴的操作(執行實際搜索)。您在錯誤情況下只保存一點點,並在常見情況下增加大量費用。

你的代碼是不太理想的唯一情況是,如果_repository.Search(name)返回一個類型,可以廉價地重複兩次,並可能便宜提供它的數(比如說,一個List),但在上下文中並不顯得案子。

+0

我沒有對存儲庫或從中返回的IEnumerable的實際類型做出任何假設。 –

+0

@EricPohl那麼,執行性能分析時,你必須這樣做。在許多情況下,無論如何,在任何方面都沒有任何一種方法總是更好,在大多數情況下,更好的做法會讓事情變得更糟。如果你不願意對數據做出任何假設,那麼你就無法比較不同的方法,超越這些方法產生正確的輸出而哪些不產生正確的輸出。現在在我看來,假設基礎假設不能有效地迭代兩次的可能性更大也更安全,但這是一個假設。 – Servy

+0

我會做一個改變 - 使用'Count'而不是'Count()',因爲你已經有了一個列表。 –

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; 
     } 
    } 
} 
+2

直到你要求第26項而不是第一個要求時纔會拋出異常。這似乎不是所要求的功能。如果有26個項目*無*應退回。 – Servy