Ответ на первую часть вопроса заключается в том, что вы правы, хотя это скорее случай небрежной терминологии, чем опечатка или ошибка. (Проще говоря, компилятор не присваивает значения переменным ... это происходит только при выполнении кода, сгенерированного компилятором.)
Более технически точный пересчет будет:
"... потому что компилятор может генерировать код, который может привести к записи значения в память для переменной-члена singleton до вызова конструктора singleton, и созданный объект был вспыхнул в памяти. "
Подобные вещи чаще всего случаются на уровне компилятора собственного кода, когда компилятор (юридически) переупорядочивает инструкции или просто в результате конвейерной обработки памяти. Модель памяти Java специально позволяет это, так что компилятор может генерировать код, который работает быстрее на многоядерных машинах. (С другой стороны, ваш многопоточный код должен синхронизироваться требуемым образом, иначе он может быть ненадежным.)
(Теоретически, для компилятора байт-кода также возможно переупорядочить байт-коды, но есть вероятность, что он этого не сделает. В компиляторе байт-кода мало что дает для детальной оптимизации. Действительно, это может быть вредно, поскольку потенциально усложняет работу оптимизатора JIT-компилятора.)
Я оставлю дела на C # и VB кому-то, кто знаком со спецификациями этих языков.