2013-05-20 18 views
2

我有一個通用集合,其中包含5000多個項目。所有項目都是獨一無二的,所以我使用SingleOrDefault從集合中提取一個項目。今天我用紅門螞蟻探查器來查看代碼,發現我的SingleOrDefault調用有5000萬次迭代(〜3.5秒),有1800萬次命中,而當我將它更改爲FirstOrDefault時,它有900萬次命中(〜1.5秒)。FirstOrDefault比SingleOrDefault顯着快於查看ANTS分析器

我使用SingleOrDefault,因爲我知道集合中的所有項都是唯一的。

編輯:問題將是爲什麼FirstOrDefault比SingleOrDefault更快,即使這是我們應該使用SingleOrDefault的確切場景。

+3

有問題嗎? – cadrell0

+1

如果您已經*知道*這些元素是唯一的,那麼'SingleOrDefault'完成的額外工作是不必要的。 –

回答

3

SingleOrDefault(predicate)確保至多有一個項目與給定的謂詞匹配,因此即使它在收集開始附近找到匹配的項目,仍然需要繼續到IEnumerable的末尾。

FirstOrDefault(predicate)只要它在集合中找到匹配項就會停下來。如果您的「第一次匹配」均勻分佈在您的IEnumerable中,那麼平均來說,您必須通過IEnumerable的一半。

對於N項的序列,SingleOrDefault將運行謂語N次,FirstOrDefault將運行謂詞(平均)N/2倍。這解釋了爲什麼您看到SingleOrDefault的「點擊率」是FirstOrDefault的兩倍。

如果您知道你永遠只能有一個匹配的項目,因爲您的收藏來源是由你和你的系統進行控制,那麼你很可能最好使用FirstOrDefault。例如,如果您的收藏集來自用戶,則可以使用SingleOrDefault作爲對用戶輸入的檢查。

6

SingleOrDefault()如果存在多個,則會引發異常。爲了確定這一點,它必須驗證不超過一個。

另一方面,FirstOrDefault()可以停止尋找一旦找到一個。因此,我預計在很多情況下它會快得多。

+0

只需添加到此答案中:當您必須確保該值實際上是唯一的時,請使用'Single(OrDefault)(...)'。否則,「First(OrDefault)(...)'更快。 – Tory

1

FirstOrDefault將在第一次命中時返回。 SinglerOrDefault不會在第一次擊中時返回,但也會查看所有其他元素以檢查其唯一性。所以FirstOrDefault在大多數情況下會更快。 Idf你不需要唯一性檢查FirstOrDefault。

1

我很懷疑SingleOrDefaultFirstOrDefault之間的選擇將是您的瓶頸。我認爲剖析工具有望突出更大的魚來炒。您自己的指標顯示,對於任何給定的迭代來說,這相當於幾乎難以察覺的時間單位。

但我建議使用與您的期望相匹配的那個。也就是說,有多於一個匹配謂詞錯誤?如果是,請使用強制執行期望的方法。 SingleOrDefault。 (同樣,如果有沒有也是一個錯誤,只需使用Single。)如果它不是多個錯誤,請隨意使用First變體。

現在它應該變得很明顯,爲什麼一個人可能比其他人稍微快一些,正如其他答案所討論的那樣。一種是強制約束,這當然是通過執行邏輯來完成的。另一個不是執行那個特定的約束,因此不會被它推遲。

0

我已經使用LinqPad運行測試,它表明使用Single和SingleOrDefault的查詢比使用First或FirstOrDefault的查詢更快。這些測試是對大數據集的相當簡單的查詢(不涉及連接)。我沒有想到這會是結果,實際上我試圖向另一個開發人員證明我們應該使用First和FirstOrDefault,但是當證明Single的實際速度更快時,我的論據基礎已經失效。有些情況下,第一個速度更快,但不要認爲這是一攬子案例。

相關問題