Может кто-нибудь объяснить, почему приведенный ниже код при запуске иногда приводит к некоторому «NULL!» строки, записываемые в консольное окно?
(Это вопрос TL; DR , читайте дальше)
Это происходит не каждый раз, и вам может понадобиться запустить этот код несколько раз, но достаточно скоро вы увидите строку "NULL!" выводится в окно консоли вместо числа.
По сути, он инициализирует (используя синтаксис сокращенной инициализации коллекции) универсальную коллекцию пользовательских типов (List<Thing>
), которая содержит одно свойство, которое является ссылкой на другой пользовательский тип (Numb
). Numb
предопределено в собственной коллекции (nnn
), и объекты из этой коллекции создаются с использованием сокращенного синтаксиса инициализатора объекта из в инициализаторе коллекции с использованием лямбды для выбора случайного объекта на основании единственного 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; }
}
}