Why do I NOT get warnings about uninitialized readonly fields?
The C# compiler is kind enough to give you a "field is never assigned to" warning if you forget to initialize a readonly member which is private or internal, or if the class in which it is being declared is internal. But if the class is public, and the readonly member is public, protected or protected internal, then no warning for you!
Does anyone know why?
Sample code which demonstrates the conditions under which the warning is issued, and the conditions under which the warning is not issued:
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: For a moment you might think that the compiler refrains from issuing the warning in the case of public and protected members because it is reasonable to expect that derived classes might initialize the field. This theory does not hold any water for a number of reasons:
An internal class may be subclassed, but the compiler does not refrain from issuing the warning in that case.
The compiler fails to issue the warning even in the case of a sealed class, as Test3 in the sample code demonstrates.
The warning makes sense for the sake of the integrity of the base class regardless of what a derived class may or may not do.
A class is expressly prohibited by the language from initializing a readonly member of a base class. (Thanks, Jim Mischel.)
EDIT2: If my memory serves me well, Java gives all the proper warnings in all cases, regardless of whether the uninitialized final member is public, protected or private, and regardless of whether the class containing it is public or visible only within its package.
The short answer: this is an oversight in the compiler.
The longer answer: the heuristic which determines what warnings to issue for members and locals that are declared and never used, or written and never read, or read and never written, does not take the read-only-ness of the field into consideration. As you correctly note, it could, and thereby issue warnings in more cases. We could say that a public readonly field that is not initialized in any ctor "will always have its default value" for example.
I'll mention it to Neal in the new year and we'll see if we can improve those heuristics in Roslyn.
Incidentally, there are a number of situations in which a warning of this sort could be issued (regardless of read-only-ness) but we do not do so. I am not in my office today so I don't have my list of all those situations handy, but suffice to say there are a lot of them. It was stuff like "the field is declared as public and is in a public nested class of an internal class". In that situation the field is effectively internal and we can do the warning, but sometimes we do not.
One day many years ago I changed the heuristic so that every field that could be statically known to be unused produced a warning, and when that change made it into the internal version of the C# compiler that we use to compile the class libraries that are written in C#, all hell broke loose. Those guys always compile with "warnings as errors" turned on, and suddenly they started getting warnings on all kinds of fields that were deliberately initialized or used onl via reflection, and other dynamic techniques. I broke the build in a major way. Now, one might argue that hey, these guys should fix their code so that it suppresses the warning (and I did argue that) but ultimately it turned out to be easier to back the warning heuristic off to its previous level. I should have made the change more gradually.
This is MSDN Documentation: Compiler Warning (level 4) CS0649:
Field 'field' is never assigned to, and will always have its default value 'value'
The compiler detected an uninitialized private or internal field declaration that is never assigned a value.
So, for non-internal and non-private fields you shouldn't expect to have a warning.
But I think the main reason is that C# compiler believes that you should initialize all the things that are accessible just from your assembly. I guess C# compiler left it to the others to initialize non-private and non internal fields in their assembly.
But I tested protected internal
and I don't know why C# compiler doesn't warn about it.
If it is public (or better not private) it can be used by another class outside your project. This is important to build libraries who should be used by others. If you would get a warning for every not used public property, field or method you wouldn't see the real problems.
链接地址: http://www.djcxy.com/p/21076.html上一篇: const,只读和可变值类型