2014-05-02 109 views
3

我有從C#書驗證碼:強制LINQ重新執行?

int minSize = 10000; 
var bigFiles = from file in GetAllFilesInDirectory(@"c:\") 
where new FileInfo(file).Length > minSize 
select file; 

var filesOver10k = bigFiles.ToArray(); 

minSize = 100000; 
var filesOver100k = bigFiles.ToArray(); 

minSize = 1000000; 
var filesOver1MB = bigFiles.ToArray(); 

minSize = 10000000; 
var filesOver10MB = bigFiles.ToArray(); 

筆者表示,將重新評估該查詢每次ToArray的()被調用。我想做類似的事情。我需要查詢一本書中每個字母的使用次數;目前我使用的是這樣的:

string alphabet="abcdefghijklmnopqrstuvwxyz"; 

foreach(char a in alphabet) 
{ 
var stat_letter=book2.book.Sum(b=>b.chapter.Sum(l=>l.line.Sum(w=>w.word.ToLower().Count(c=>c.Equals(a))))); 
Console.WriteLine(a + ":" + stat_letter.ToString()); 
} 

輸出我得到:

a: 31278 
b: 6263 
c: 14561 
[...] 

我想改變它的工作很像書例如:

char q = 'a'; 
var stat_letter = book2.book.Sum(b=>b.chapter.Sum(l=>l.line.Sum(w=>w.word.ToLower().Count(c=>c.Equals(q))))); 

string alphabet="abcdefghijklmnopqrstuvwxyz"; 

foreach(char a in alphabet) 
{ 
q=a; 
Console.WriteLine(q + ":" + stat_letter.ToString()); 
} 

輸出我從中得到:

a: 31278 
b: 31278 
c: 31278 
[...] 

它看起來像在這種情況下查詢不重新評估。有什麼辦法強制它?其實我的動機是檢查它是否會加快程序執行速度,所以如果你認爲它不會,那也是我想知道的...

回答

-1

這並不是說查詢不會重新評估,它是LINQ使用延遲執行在可能的情況。如果您正在查看它正在使用延遲執行,並且每次調用ToArray(),查詢都會在該時間點在集合上執行。在您的示例中,一個或多個查詢運算符(Sum肯定會)強制執行,因此如果您一直試圖反覆運行它,則無關緊要,查詢已在該時間點針對集合運行而實際的結果是存儲在該變量中的內容。基本上,只是使用你的工作代碼,因爲這是做到這一點的慣用方式。

+0

Downvoter關心評論?我的解釋與下面的答案大致相同,其中有6個upvotes ...也許最後一句只是我的意見,但答案是準確的。 – evanmcdonnal

2

您計算了值並將其保存在變量中。當然,它不會被重新評估。 但你可以做到以下幾點:

Func<char,int> stat_letter_func = q => book2.book.Sum(b=>b.chapter.Sum(l=>l.line.Sum(w=>w.word.ToLower().Count(c=>c.Equals(q))))); 

string alphabet="abcdefghijklmnopqrstuvwxyz"; 

foreach(char a in alphabet) 
{ 
    Console.WriteLine(a + ":" + stat_letter_func(a).ToString()); 
} 
7

Sum返回int(使用您選擇的過載)不是一個IEnumerable。這意味着它會立即進行評估,因爲它需要intint的值不能推遲。

雖然有幾種重構代碼的方式來延遲執行,但我更願意做的是創建一個方法(或者一個lambda,真的是相同的概念),它計算您想要的輸入值有,而不是突變查詢依賴的變量。

Func<char, int> computeLetterCount = letter => book2.book.Sum(
    b=>b.chapter.Sum(
     l=>l.line.Sum(
      w=>w.word.ToLower().Count(c=>c.Equals(letter))))); 

現在你可以這樣寫:

foreach(char a in alphabet) 
{ 
    Console.WriteLine(a + ":" + computeLetterCount(a)); 
} 
+0

將'q'更改爲'a'。 –