About unassigned variables

Just curious, I'm not trying to solve any problems.

Why do I need to assign only local variables?

In the following example:

class Program { static int a; static int b { get; set; } static void Main(string[] args) { int c; System.Console.WriteLine(a); System.Console.WriteLine(b); System.Console.WriteLine(c); } } 

Why does a and b only give me a warning, and c gives me an error?

Also, why can't I just use the default value of the value type and write the following code?

  bool MyCondition = true; int c; if (MyCondition) c = 10; 

Does it have anything to do with memory management?

+13
source share
3 answers

Because other variables are initialized to default .

John Skeet has already found some interesting words on this issue:

For local variables, the compiler has a good understanding of the stream โ€” it can see the โ€œreadingโ€ of the variable and the โ€œwritingโ€ of the variable, and prove (in most cases) that the first write will occur before the first read.

This does not apply to instance variables. Consider a simple property - how do you know if someone installs it before they receive it? This makes it practically unreasonable to provide reasonable rules - either you must make sure that all fields are set in the constructor or allow them to have default values. The C # team chose the latest strategy.

and here is the corresponding C # language specification:

5.3 Specific purpose

At a given place in the executable code of a member of a function, a variable is said to be definitely assigned, if the compiler can prove, by a specific analysis of the static stream (section 5.3.3), that the variable has been automatically initialized or was the target of at least one purpose.

5.3.1 Initially assigned variables

The following categories of variables are classified as originally assigned:

  • Static Variables

  • Instance variables of the class.

  • Instance variables of the originally assigned structure variables.

  • Array elements

  • Value Parameters.

  • Reference parameters.

  • Variables declared in a catch or foreach clause.

5.3.2 Initially unassigned variables

The following categories of variables are classified as initially Unassigned:

  • Instance variables of initially unassigned structural variables.

  • Output options, including this instance variable struct constructors.

  • Local variables other than those declared in a catch or foreach clause.

+20
source

Tim gives a good answer to your first question, but I can add a few more details.

Your first question is basically "locals should definitely be assigned, so why not do the same field restrictions?" Tim points out that John points out that this is actually quite complicated. With locals it is almost always crystal clear when the local is read first and when it is first written. In cases where this is not clear, the compiler can make reasonable conservative guesses. But with fields, in order to know when the first read and first write occurs, you need to know all kinds of things about which methods are called in which order.

In short, the analysis of local residents requires local analysis; analysis should not go past the block containing the declaration. Field analysis requires global analysis. It is a lot of work; itโ€™s easier to say that the fields are initialized with default values.

(Now, of course, this global analysis can be done; my new work is likely to include just such an analysis).

Your second question is basically "Well, then, if automatic assignment of default values โ€‹โ€‹is enough for the fields, then why is it not so good for the locals?" and the answer is "because the inability to assign a local variable and accidentally get the default value is a common source of errors." C # has been carefully designed to discourage programming practices that lead to annoying errors, and this is one of them.

+25
source

The CLR provides a strong guarantee that local variables are initialized with a default value. But this guarantee has limitations. Its ability to recognize blocks of regions inside the method body is lacking. They disappear after the compiler translates the code into IL. Scope is a language construct that has no parallel in the CLI and cannot be expressed in IL.

You can see that this is happening incorrectly in a language such as VB.NET. This contrived example shows the behavior:

 Module Module1 Sub Main() For ix = 1 To 3 Dim s As String If ix = 2 Then s = "foo" If s Is Nothing Then Console.WriteLine("null") Else Console.WriteLine(s) Next Console.ReadLine() End Sub End Module 

Conclusion:

 null foo foo 

Or, in other words, the local variable s was initialized only once and after that it stores the value. Of course, this gives the ability to create mistakes. The VB.NET compiler generates a warning for it and has simple syntax to avoid it (like new). A managed language such as C ++ / CLI has the same behavior, but does not generate diagnostics at all. But the C # language gives a stronger guarantee, it generates an error.

This rule is called a "specific task." The exact rules are described in detail in the C # Language Specification, chapter 5.3.3

A certain assignment check has its limitations. It works well for local variables, since their scope is very limited (private to the method body), and you cannot get to them using Reflection. It is much more difficult to do with the fields of the class, this requires an analysis of the entire program, which may be required to achieve what the compiler can see. Like code in another assembly. This is why the C # compiler can only warn about this, but cannot reject code outside of the law.

+9
source

All Articles