强制LINQ再次执行?

Jac*_*des 3 c# linq

我从ac#book获得了这个代码:

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();
Run Code Online (Sandbox Code Playgroud)

作者说,每次调用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() );
}
Run Code Online (Sandbox Code Playgroud)

我得到的输出:

a: 31278
b: 6263
c: 14561
[...]
Run Code Online (Sandbox Code Playgroud)

我想把它改成像书的例子一样工作:

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() );
}
Run Code Online (Sandbox Code Playgroud)

我得到的输出:

a: 31278
b: 31278
c: 31278
[...]
Run Code Online (Sandbox Code Playgroud)

在这种情况下,查询似乎不会重新评估.有没有办法强迫它?实际上我的动机是检查它是否会加速程序的执行,所以如果你认为它不会,那也是我想知道的事情......

Ser*_*rvy 7

Sum返回一个int(使用你选择的重载)而不是IEnumerable.这意味着它会立即进行评估,因为它需要它int.a的值int不能推迟.

虽然有几种方法可以重新构建代码以延迟执行,但我更喜欢做的是创建一个方法(或者一个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)))));
Run Code Online (Sandbox Code Playgroud)

你现在可以写:

foreach(char a in alphabet)
{
     Console.WriteLine(a + ":" + computeLetterCount(a) );
}
Run Code Online (Sandbox Code Playgroud)