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

Cra*_*gTP 3 c# random collections initialization

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

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

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

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

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

我的怀疑告诉我这与在对象/集合初始化器场景中使用调用(特别是多次调用)有关rnd.Next().

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

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Random rnd = new Random();

            var nnn = new List<Numb> {
                new Numb() {
                    num = 1
                },
                new Numb() {
                    num = 2
                }
            };

            new List<Thing> {
                new Thing() {
                    numb = nnn.Where(n => n.num==rnd.Next(1,3)).FirstOrDefault()
                },
                new Thing() {
                    numb = nnn.Where(n => n.num==rnd.Next(1,3)).FirstOrDefault()
                },
                new Thing() {
                    numb = nnn.Where(n => n.num==rnd.Next(1,3)).FirstOrDefault()
                },
                new Thing() {
                    numb = nnn.Where(n => n.num==rnd.Next(1,3)).FirstOrDefault()
                }
            }.ForEach(t => Console.WriteLine(t.numb!=null ? t.numb.num.ToString() : "NULL!"));

            Console.ReadLine();
        }
    }

    public class Thing
    {
        public Numb numb { get; set; }
    }

    public class Numb
    {
        public int num {get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 6

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

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

这将是:

  • 开始迭代,得到第一个Numb- 让我们调用它n1
  • 生成一个随机数,1或2 - 让我们调用它 x
  • 检查是否n1.num == x,如果是,则产生
  • 假设上一步匹配,它会......
    • 继续迭代,得到第二个Number- 让我们调用它n2
    • 生成另一个随机数,1或2 - 让我们调用它y
    • 检查是否n2.num == y,如果是,则产生
    • 假设上一步匹配,则返回null

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