linq 查询中的随机数
Random numbers in linq queries
惰性语句中的随机数据在运行时可能会得到不同的评估,这是真的吗?使用以下代码,我多次看到 "wow" 打印到控制台。但是,如果我强制查询结果(即在 xs
和 ys
上调用 ToList()
),事情似乎工作正常。
public static void Main(string[] args)
{
var generator = new Random();
var xs = from x in Enumerable.Range(0, 20000)
select generator.Next();
var ys = from y in Enumerable.Range(0, 5000)
select generator.Next();
foreach (var x in xs)
{
var q1 = from y in ys where y > x select y;
var q2 = from y in ys where y > x select y;
if (!q1.SequenceEqual(q2))
Console.WriteLine("wow!");
}
Console.WriteLine("done");
Console.ReadLine();
}
我怀疑这与 linq 查询是 "lazy" 这一事实有关。这准确吗?
Is it true that random data inside a lazy statement might get evaluated differently at runtime?
真实的是,正如您所写:
I suspect that this has to do with the fact that linq queries are "lazy". Is this accurate?
另外一个重要的事情是它们不会在执行后 "materialized"/"cached",所以每次执行它们时,它们都会重新生成。
这一行
if (!q1.SequenceEqual(q2))
Console.WriteLine("wow!");
将导致 q1
和 q2
可枚举的计算,每个将导致 ys
的枚举。因此 ys
将是 "generated" 两次 foreach
循环的每个循环。
所以,考虑到 foreach
循环将执行 20000 "cyles",ys 将是 "generated" 40000 次。
Random.Next()
会被执行20000 + (20000 * 2 * 5000)次,其中
20000: the xs sequence, used only once by the foreach cycle:
20000 * 2 * 5000: 20000 cycles in which the ys sequence is used twice
请注意如果发生以下情况会发生什么:
var xs = (from x in Enumerable.Range(0, 20000)
select generator.Next()).ToArray();
var ys = (from y in Enumerable.Range(0, 5000)
select generator.Next()).ToArray();
这里是 "materializing" 数组中的可枚举项(准确地说是两个数组)。 Random.Next()
会调用20000 + 5000
次的grandtotal,直接在这两行中完成。 xs
和ys
的枚举不会产生新的随机数。
惰性语句中的随机数据在运行时可能会得到不同的评估,这是真的吗?使用以下代码,我多次看到 "wow" 打印到控制台。但是,如果我强制查询结果(即在 xs
和 ys
上调用 ToList()
),事情似乎工作正常。
public static void Main(string[] args)
{
var generator = new Random();
var xs = from x in Enumerable.Range(0, 20000)
select generator.Next();
var ys = from y in Enumerable.Range(0, 5000)
select generator.Next();
foreach (var x in xs)
{
var q1 = from y in ys where y > x select y;
var q2 = from y in ys where y > x select y;
if (!q1.SequenceEqual(q2))
Console.WriteLine("wow!");
}
Console.WriteLine("done");
Console.ReadLine();
}
我怀疑这与 linq 查询是 "lazy" 这一事实有关。这准确吗?
Is it true that random data inside a lazy statement might get evaluated differently at runtime?
真实的是,正如您所写:
I suspect that this has to do with the fact that linq queries are "lazy". Is this accurate?
另外一个重要的事情是它们不会在执行后 "materialized"/"cached",所以每次执行它们时,它们都会重新生成。
这一行
if (!q1.SequenceEqual(q2))
Console.WriteLine("wow!");
将导致 q1
和 q2
可枚举的计算,每个将导致 ys
的枚举。因此 ys
将是 "generated" 两次 foreach
循环的每个循环。
所以,考虑到 foreach
循环将执行 20000 "cyles",ys 将是 "generated" 40000 次。
Random.Next()
会被执行20000 + (20000 * 2 * 5000)次,其中
20000: the xs sequence, used only once by the foreach cycle:
20000 * 2 * 5000: 20000 cycles in which the ys sequence is used twice
请注意如果发生以下情况会发生什么:
var xs = (from x in Enumerable.Range(0, 20000)
select generator.Next()).ToArray();
var ys = (from y in Enumerable.Range(0, 5000)
select generator.Next()).ToArray();
这里是 "materializing" 数组中的可枚举项(准确地说是两个数组)。 Random.Next()
会调用20000 + 5000
次的grandtotal,直接在这两行中完成。 xs
和ys
的枚举不会产生新的随机数。