Компилятор С# достаточно добр, чтобы дать вам предупреждение "поле никогда не назначается", если вы забыли инициализировать член readonly, который является частным или внутренним, или если класс, в котором он объявляется, является внутренним. Но если класс является общедоступным, а член readonly является общедоступным, защищенным или защищенным внутренним, то для вас нет предупреждений!
Кто-нибудь знает, почему?
Пример кода, который демонстрирует условия, при которых выдается предупреждение, и условия, при которых предупреждение не выдается:
namespace Test1
{
class Test1
{
#if TRY_IT
public readonly int m; //OK: warning CS0649: Field is never assigned to, and will always have its default value 0
protected readonly int n; //OK: warning CS0649: Field is never assigned to, and will always have its default value 0
internal readonly int o; //OK: warning CS0649: Field is never assigned to, and will always have its default value 0
private readonly int p; //OK: warning CS0649: Field is never assigned to, and will always have its default value 0
protected internal readonly int q; //OK: warning CS0649: Field is never assigned to, and will always have its default value 0
Test1()
{
if( p != 0 ) //To avoid warning 'The field is never used'
return;
}
#endif
}
public class Test2
{
#if TRY_IT
private readonly int m; //OK: warning CS0649: Field is never assigned to, and will always have its default value 0
internal readonly int n; //OK: warning CS0649: Field is never assigned to, and will always have its default value 0
Test2()
{
if( m != 0 ) //To avoid warning 'The field is never used'
return;
}
#endif
public readonly int o; //Blooper: no warning about field never assigned to.
protected readonly int p; //Blooper: no warning about field never assigned to.
protected internal readonly int q; //Blooper: no warning about field never assigned to.
}
public sealed class Test3
{
public readonly int m; //Blooper: no warning about field never assigned to.
}
}
EDIT: На мгновение вы можете подумать, что компилятор воздерживается от выдачи предупреждения в случае публичных и защищенных членов, потому что разумно ожидать, что производные классы могут инициализировать это поле. Эта теория не содержит воды по ряду причин:
-
Внутренний класс может быть подклассом, но компилятор не воздерживаться от выдачи предупреждения в этом случае.
-
Компилятор не может выдать предупреждение даже в случае запечатанного класс, как демонстрирует Test3 в примере кода.
-
Предупреждение имеет смысл ради целостности базы независимо от того, какой производный класс может или не может выполнять.
-
Класс явно запрещен языком при инициализации readonly член базового класса. (Спасибо, Джим Мишель.)
EDIT2: Если моя память мне хорошо помогает, Java дает все правильные предупреждения во всех случаях, независимо от того, является ли неинициализированный конечный элемент общедоступным, защищенным или закрытым и независимо от того, содержит ли класс, содержащий он является общедоступным или видимым только внутри его пакета.