Обратите внимание, что поля неявно инициализируются в null
, так что это влияет только на переменные. В чистом c # вы не можете запросить значение неинициализированного поля (вам нужно «определенное присваивание»), так что это не вопрос.
Вы можете сделать это, злоупотребив IL, хотя - объявив параметр out
и используя DynamicMethod
, чтобы написать метод, который не назначает его (допустимый в IL, но не в C # ). И тогда вы обнаружите, что вы увидите null
s.
Это, в свою очередь, происходит из-за флага IL (.locals init
), который говорит: «очистите для меня стек перед входом в этот метод» в , вызывающем код (C #). Компилятор C # всегда устанавливает этот флаг. Если вы снова злоупотребляете IL, чтобы написать метод, который не устанавливает этот флаг, вы можете увидеть мусор. Это может быть что угодно . Но к этому моменту вы заслуживаете исключений, которые вы получаете:)
Вот пример первого (не второго, который является более сложным):
delegate void AbuseMe(out object foo);
static void Main() {
DynamicMethod dyn = new DynamicMethod("Foo",
typeof(void), new[] { typeof(object).MakeByRefType() });
dyn.GetILGenerator().Emit(OpCodes.Ret);
AbuseMe method = (AbuseMe) dyn.CreateDelegate(typeof(AbuseMe));
object obj; // this **never** gets assigned, by **any** code
method(out obj);
Console.WriteLine(obj == null);
}
Для пояснения, код DynamicMethod
просто пишет эквивалент этого кода, недопустимый в C #:
static void Foo(out object whatever) { } // note, whatever is not assigned
Это работает, потому что в отношении CLR out
не существует - существует только ref
. Так что это не недействительный IL - только язык (C #) придает значение out
и требует, чтобы ему было присвоено значение.
Проблема в том, что Main()
все еще имеет флаг .locals init
; поэтому за кадром obj
очищается до null
(ну, все пространство стека просто стирается). Если бы я компилировал из IL без этого флага (и имел какой-то другой код, чтобы сделать пространство стека грязным), я мог бы видеть мусор. Вы можете увидеть больше о .locals init
в блоге Лиран Чен .
Но чтобы ответить на вопрос:
- для полей: поля неинициализированного ссылочного типа
null
- гарантируется спецификацией
- для переменных: вы не можете спрашивать , но как подробности реализации (от этого не следует зависеть): да, это будет
null
даже хотя вы не можете спросить; p