8

in C#, if i do something like:

int x;

then hit F10, I see that there's a zero stored in x.

but when i try to use x, it tells me that i should initialize it .. why is that ? there's supposed to be a zero there, right ?

the same thing is also true about arrays, so:

int[]a = new int[5];

if we F10 that, we'll see that all the ints in there are zeros..

What's going on ? and why should i ever MUST initialize a variable in C# unlike in C++ ?

vexe
  • 5,433
  • 12
  • 52
  • 81
  • Because that's what the compiler expects it's not interpreted like VB and if this is a local variable I would definitely recommend initializing it to zero.. it's best to not assume When I initialize string I always initialize the variable to string.Empty and int's to 0 – MethodMan Jul 13 '12 at 00:34
  • By F10 you mean Visual Studio debugger behaviour? – Zong Jul 13 '12 at 00:34
  • `0` is the default value of `integer`. You could better initialize to a specific value. – Lion Jul 13 '12 at 00:34
  • yes by F10 I mean debugging in Visual Studio. – vexe Jul 13 '12 at 00:37
  • @VeXe I deleted my answer cause cannot replicated x having ? in it instead of 0 as default. So is your second question question on this sort of syntax int? x; – HatSoft Jul 13 '12 at 00:46

5 Answers5

7

It's a compile time error trying to help you reduce bugs in your code due to un-initialized variables. Very useful.

http://msdn.microsoft.com/en-us/library/4y7h161d(VS.80).aspx

More reading:

http://blogs.msdn.com/b/abhinaba/archive/2005/11/08/490248.aspx

Some words on disabling the error (you can't just to warn you - it's not a warning):

http://social.msdn.microsoft.com/Forums/en/csharplanguage/thread/a073ccea-c43b-4536-be76-41949f0e2135

and

http://blogs.msdn.com/b/ericlippert/archive/2009/10/12/absence-of-evidence-is-not-evidence-of-absence.aspx (proves to be most informative on the subject)

and even more discussing relationship between "localsinit" IL flag (that forces default values to be set for locals) and its relation to "double assignment" (C# forces you to write int v=0 even if it is already there). And if you want to read even deeper - "localsinit" defined in section I.12.2 of ECMA-335 available here.

Daniel Mošmondor
  • 19,718
  • 12
  • 58
  • 99
  • 4
    Incomplete answer. Some variables in C# are indeed initialized to a default value (such as static variables, or instance variables). On the other hand, local variables are not initialized to a default value. – Christopher Berman Jul 13 '12 at 00:40
  • 1
    Even more reading : http://stackoverflow.com/questions/8931226/are-c-sharp-uninitalized-variables-dangerous/8933935#8933935 from Eric Lippert – Mike Park Jul 13 '12 at 00:41
  • considering that the error code for the uninitialized problem is CS0165, can I disable it ? – vexe Jul 13 '12 at 00:41
  • 5
    You'd be far better off just initializing your local variables rather than disabling compiler errors. – Christopher Berman Jul 13 '12 at 00:42
  • 3
    @ChristopherBerman, all local variables *are* initialized to 0 by run-time due to C# setting "localsinit" flag to force memory allocated for local variables to be set to 0. It is compiler that (rightfully in my opinion) insists on initialization. – Alexei Levenkov Jul 13 '12 at 01:03
  • Good point. The distinction between 'initialized' and 'assigned'. – Christopher Berman Jul 13 '12 at 01:09
  • @AlexeiLevenkov Without wanting to be a nasty pedant, that's not quite true; Creating a new local string will not be initialised to 0, it will be null; but you're absolutely correct that the runtime should insist on initialisation. – Russ Clarke Jul 13 '12 at 01:17
  • @RussC, Not sure what is not quite true: string is reference type - the space for variable is initialized with 0 which represents `null` pointer. – Alexei Levenkov Jul 13 '12 at 01:20
  • @AlexeiLevenkov indeed, hence my apology for being pedantic; but that's just a conformity if you create a new string 'str' and test is 'str == 0', it won't compile but testing uf 'str == null' will. – Russ Clarke Jul 13 '12 at 01:24
  • The Eric Lippert blog linked in this answer is a very good way of explaining this compiler error. – Russ Clarke Jul 13 '12 at 01:38
4

Simply put, because that's the way C# works. From the C# Language Specification:

5.3.2 Initially unassigned variables

The following categories of variables are classified as initially unassigned:

· Instance variables of initially unassigned struct variables.

· Output parameters, including the this variable of struct instance constructors.

· Local variables, except those declared in a catch clause or a foreach statement.

On the other hand:

5.3.1 Initially assigned variables

The following categories of variables are classified as initially assigned:

· Static variables.

· Instance variables of class instances.

· Instance variables of initially assigned struct variables.

· Array elements.

· Value parameters.

· Reference parameters.

· Variables declared in a catch clause or a foreach statement.

Community
  • 1
  • 1
Christopher Berman
  • 719
  • 1
  • 5
  • 21
3

Simple... because the compiler insists that you initialize local variables before using them. This prevents a whole category of mistakes associated with failure to initialize.

If you look at the IL generated from the following few statements:

int x;
Console.WriteLine("hello");
int y=5;
x=6;
Console.WriteLine(x+y);

you see the following:

//notice no ops related to x prior to console.writeline
IL_0000:  ldstr       "hello"
IL_0005:  call        System.Console.WriteLine
IL_000A:  ldc.i4.5    
IL_000B:  stloc.1        //create/store y
IL_000C:  ldc.i4.6    
IL_000D:  stloc.0        //x is really only created right here
IL_000E:  ldloc.0     
IL_000F:  ldloc.1     
IL_0010:  add         
IL_0011:  call        System.Console.WriteLine

if you're seeing a value for x prior to it's storing in IL, then it's a debugger trick.

spender
  • 117,338
  • 33
  • 229
  • 351
  • And a misleading trick at that. Weird that the debugger wouldn't draw the distinction. – Christopher Berman Jul 13 '12 at 00:46
  • Well, I suppose the debugger has a notion of the name associated with each local, so displays whatever ldloc.[index of x] dumps on the stack, even before it is initially stored/"declared" in IL. – spender Jul 13 '12 at 00:50
2

The auto-initialization is a runtime security feature I believe, not a language guarantee. It happens that .NET zeroes variables, but that doesn't have to be true with every framework.

Note that for arrays, it is guaranteed.

user541686
  • 205,094
  • 128
  • 528
  • 886
  • so for arrays, there's not luck about it, there will be zeros everytime right ? but why is that ? I mean, arrays are just a bunch of adjacent-same type variables, so an array of 10 ints is just 10 ints, shouldn't we treat each one of them with the same treatment as we did with a single int ? – vexe Jul 13 '12 at 00:54
  • It have to be 0 filled for all *compliant* implementations of CLI (like .Net Framework). – Alexei Levenkov Jul 13 '12 at 01:08
  • @VeXe: That's a language design question -- what you say is basically what they do in C++, but I don't know why they did it differently in C#. It's just how the language is designed; you can't work around it. (They possibly did it this way just because it's handy, or because they don't like undefined values, but I don't know the actual reason.) Also, note that it's *much harder* (if not impossible) for the compiler to verify if you've assigned to an array member -- so it would need to either leave them with unspecified values, or just initialize them. They chose the latter. – user541686 Jul 13 '12 at 01:08
  • @AlexeiLevenkov: No kidding! That's like saying "only non-criminals have to obey the law". Kind of true by definition, isn't it? :P – user541686 Jul 13 '12 at 01:08
1

It being 0 is just luck, it could be anything, that is why you must initialize it.

Hogan
  • 69,564
  • 10
  • 76
  • 117
  • ok, this means that it could be something else right ? but in both cases there will be something stored in it, whether it's a zero or not, so when I use it, it has something stored in it, so ... ? – vexe Jul 13 '12 at 00:39
  • 1
    Default values are well defined [here](http://msdn.microsoft.com/en-us/library/83fhsxwc.aspx). A [nullable type](http://msdn.microsoft.com/en-us/library/1t3y8s4s(v=vs.100).aspx) provides an explicit means of indicating a value is not present. – HABO Jul 13 '12 at 00:47
  • What do default values have to do with this? The OP did not say he was using a boxed object so no `new` is involved. – Hogan Jul 13 '12 at 00:54
  • 0 is not just luck, but it may or may not be "default" for your type. 0 is because C# sets "localsinit" flag for each method and run-time respects it: "If the localsinit flag on the method is true, the block of memory returned is initialized to 0; otherwise, the initial value of that block of memory is unspecified" (III.3.47 of ECMA 335). – Alexei Levenkov Jul 13 '12 at 01:05