2011-09-23 61 views
3

ToArray()等方法強制評估LINQ查詢的做法是否被接受,並且是否存在用於組成最佳查詢鏈的一般啓發式方法?我經常嘗試一次性完成所有事情,因爲我注意到在這些情況下,AsParallel()在加速計算方面確實做得很好。在查詢執行沒有副作用的計算的情況下,但是需要多次通過才能獲得正確的數據,這就迫使使用ToArray()的計算是正確的方式還是更好地將查詢保留爲惰性格式?何時強制LINQ查詢評估?

回答

2

將查詢保留在惰性表單中,直到您開始多次評估查詢,或者甚至更早,如果您需要它們以另一種形式您正處於變量值捕獲的變量中。

如果查詢包含要避免多次執行的複雜投影(例如,爲包含大量元素的序列構建複雜對象),您可能需要評估。在這種情況下,評估一次並迭代多次會更加安全。

如果您想要將結果返回給另一個需要特定類型的集合的API,則可能需要另一種形式的結果

如果查詢捕獲的變量不在本地範圍內,您可能想要或需要阻止訪問修改後的關閉。在實際評估查詢之前,您有可能在其他代碼的「背後」更改其值;當評估發生時,它將使用這些值而不是構建查詢時出現的值。 (但是,可以通過在另一個具有本地作用域的變量中複製這些值來解決此問題)。

1

當您需要使用數組時,您通常只會使用ToArray(),就像使用期望數組的API一樣。只要你不需要訪問查詢的結果,並且你不侷限於某種連接上下文(就像LINQ to SQL或LINQ to Entities的情況那樣),那麼你可能只是以惰性形式保留查詢。

+1

調用'Count()'作爲訪問查詢的結果嗎? – svick

+0

這取決於實現 - 它可能迭代每個結果來計算每個結果,或者可能會在SELECT COUNT ... SQL語句中進行優化。 –

+0

使用LINQ to Entities和LINQ to SQL,Count()將懶惰地評估。你可以調用ToList(),Count()或ToArray()。Count()來獲得直接結果。請參閱http://msdn.microsoft.com/en-us/library/bb308959.aspx –

2

如果您不反對使用「實驗」庫,則可以使用Interactive Extensions庫中的EnumerableEx.Memoize擴展方法。

該方法提供了一種兩全其美的選項,其中底層序列是按需計算的,但不是在次要遍次上重新計算。在我看來,另一個小好處是,退貨類型不是可變收集,因爲它將與ToArrayToList一起使用。

+0

問題是「何時?」,而不是「如何?」。 – svick

+0

@svick,這是我認爲有用的信息。我的想法之一是嘗試和執行某種記憶,以便我可以避免重新計算查詢。 – davidk01