user4568872
user4568872

Reputation:

shadow 0 initialisation of variable in C#

I have started to learn C# after C++ recently. In book I saw code

public class Panda
{
    public string name;
    public static int population;
    public Panda(string n)
    {
        name = n;
        population += 1;
    }
}

Then I create 2 objects

Panda first=new Panda("po");
Panda second = new Panda ("bo");

After that I put the value of population in console=2. Why 2? I did not init. population. I only increment it. Can someone explain it?

Upvotes: 0

Views: 95

Answers (2)

dbc
dbc

Reputation: 116981

c# (really, the entire .Net CLR) is designed to make "uninitialized variable" bugs in pure managed code impossible. Fields (static and instance) are pre-initialized to their default value by the runtime; this is why your static population has initial value 0. From the c# Language Specification, 10.4.4 Field initialization:

The initial value of a field, whether it be a static field or an instance field, is the default value (Section 5.2) of the field's type. It is not possible to observe the value of a field before this default initialization has occurred, and a field is thus never "uninitialized".

Local variables, on the other hand, are uninitialized initially. From Section 5.1.7 Local variables:

A local variable is not automatically initialized and thus has no default value. For the purpose of definite assignment checking, a local variable is considered initially unassigned.

Instead, a variable must be definitely assigned before being used. From 5.3 Definite assignment:

At a given location in the executable code of a function member, a variable is said to be definitely assigned if the compiler can prove, by static flow analysis, that the variable has been automatically initialized or has been the target of at least one assignment.

Definite assignment is a requirement in the following contexts:

  • A variable must be definitely assigned at each location where its value is obtained. This ensures that undefined values never occur. The occurrence of a variable in an expression is considered to obtain the value of the variable, except when
    • the variable is the left operand of a simple assignment,
    • the variable is passed as an output parameter, or
    • the variable is a struct-type variable and occurs as the left operand of a member access.
  • A variable must be definitely assigned at each location where it is passed as a reference parameter. This ensures that the function member being invoked can consider the reference parameter initially assigned.
  • All output parameters of a function member must be definitely assigned at each location where the function member returns (through a return statement or through execution reaching the end of the function member body). This ensures that function members do not return undefined values in output parameters, thus enabling the compiler to consider a function member invocation that takes a variable as an output parameter equivalent to an assignment to the variable. The this variable of a struct-type instance constructor must be definitely assigned at each location where that instance constructor returns.

If you try to use the value of a local variable before the compiler can prove it is assigned, you will get the compiler error Use of unassigned local variable 'name'.

Incidentally, incrementing a static variable in the way you are doing it isn't guaranteed to be thread-safe. Instead, you should do:

public static volatile int population; // Guarantee all threads see the up-to-date value.

Then later

Interlocked.Increment(ref population); // Guarantee incrementing is atomic.

Upvotes: 0

Russ Wilson
Russ Wilson

Reputation: 110

ints are not nullable, so the default value of an int is 0

So, declaring

private static int count; 

is equivalent to

private static int count = 0;

Upvotes: 1

Related Questions