在集合/对象初始化程序中使用Random.Next()

时间:2012-02-29 14:57:46

标签: c# collections random initialization

任何人都可以解释为什么下面的代码在运行时偶尔会导致一些“NULL!”字符串被写入控制台窗口?

(这是 TL; DR 问题,请继续阅读以获取更多详情)

这不会每次都发生,您可能需要运行此代码几次,但很快,您将看到一串“NULL!”输出到控制台窗口而不是数字。

本质上,它正在初始化(使用简写集合初始化程序语法)用户定义类型(List<Thing>)的通用集合,其中包含一个属性,该属性是对另一个用户定义类型的引用({{1} })。 Numb在其自己的集合(Numb)中预定义,并使用lambda中的在集合初始化程序中使用的速记对象初始值设定语法创建该集合中的对象根据它的唯一nnn属性来选择一个随机对象。

num永远不应该返回nnn.Where(n => n.num==rnd.Next(1,3)).FirstOrDefault()个对象(即NULL的默认部分),因为随机数应该只选择1或2,两者都存在在FirstOrDefault()集合中。

我的怀疑告诉我这与在对象/集合初始化方案中使用{{1>}的调用(特别是多个调用)有关。

代码(作为控制台应用程序运行):

nnn

3 个答案:

答案 0 :(得分:6)

您在谓词的每个测试中生成一个不同的随机数。所以只看一部分:

new Thing() {
    numb = nnn.Where(n => n.num==rnd.Next(1,3)).FirstOrDefault()
}

那将会:

  • 开始迭代,获取第一个Numb - 让我们称之为n1
  • 生成一个随机数,1或2 - 让我们称之为x
  • 检查是否为n1.num == x,如果是,则为其生成
  • 假设上一步没有匹配,它将......
    • 继续迭代,获得第二个Number - 让我们称之为n2
    • 生成另一个随机数,1或2 - 让我们称之为y
    • 检查是否为n2.num == y,如果是,则为其生成
    • 假设上一步没有匹配,它将返回null

换句话说,你正在查询移动目标。您希望生成一个随机数,然后针对所有值进行测试。 (然后对集合初始化程序的每个成员重复。)

答案 1 :(得分:2)

 numb = nnn.Where(n => n.num==rnd.Next(1,3)).FirstOrDefault()

当rnd恰好生成2, 1,子序列时,您将尝试匹配1 == 22 == 1,因此找不到任何匹配项。

答案 2 :(得分:0)

您的问题是您为每次比较生成一个新的随机数。

所以第一个选择概率为1/2,第二个选择概率为1/4,没有选择概率为1/4。