linq查询中的随机数

本文关键字:随机数 查询 linq | 更新日期: 2023-09-27 17:50:25

在运行时,lazy语句中的随机数据可能得到不同的评估,这是真的吗?使用下面的代码,我看到"wow"多次打印到控制台。然而,如果我强制查询的结果(即在xsys上调用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查询是"懒惰"的事实有关。这准确吗?

linq查询中的随机数

是真的,在一个懒惰的语句中的随机数据可能得到不同的评估在运行时?

事实是,正如你所写的:

我怀疑这与linq查询是"懒惰的"这一事实有关。这准确吗?

另一个重要的事情是,它们在执行后不会被"物化"/"缓存",所以每次执行它们时,它们都会被重新生成。

这条线

if (!q1.SequenceEqual(q2))
    Console.WriteLine("wow!");

将导致q1q2枚举值的求值,每个枚举值将导致ys的枚举值。因此,ys将在foreach周期的每个周期中"生成"两次。

因此,考虑到foreach周期将进行20000个"循环",ys将被"生成"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();

这里我们"物化"了一个数组(准确地说是两个数组)中的可枚举对象。Random.Next()将被调用20000 + 5000次,它将直接在这两行中完成。xsys的枚举不会产生新的随机数