Mike_R Posted April 13, 2008 Posted April 13, 2008 I was thinking about how VB.NET auto-initializes its variables if not explicitly written to before being read, something that C# does not allow. The simplest example would be something like this: ' VB.NET: Public Sub MySub() Dim j As Integer MessageBox.Show(j.ToString) End Sub The equivalent in C# would not compile: // C#: public void MySub() { int j; MessageBox.Show(j.ToString()); } The compiler would complain about "Use of unassigned local variable 'j'" at the point where 'j.ToString()' is called. So I wondered what the VB.NET code would look like when viewing the IL. I had expected to find an explicit assignment of 'j' to 0, presumably created by the VB.NET compiler. But I was surprised at what I found: .method public instance void MySub() cil managed { .maxstack 1 .locals init ( [0] int32 j) L_0000: ldloca.s j L_0002: call instance string [mscorlib]System.Int32::ToString() L_0007: call valuetype [system.Windows.Forms]System.Windows.Forms .DialogResult [system.Windows.Forms]System.Windows.Forms .MessageBox::Show(string) L_000c: pop L_000d: ret } Basically, the 'int32 j' is not assigned a value before .ToString() is called. I had expected to see 'j' being set to zero via a 'ldc.i4.0' call followed by 'stloc.0' and then the rest of the routine would proceed as shown above. That is, I had expected to see this: .method public instance void MySub() cil managed { .maxstack 1 .locals init ( [0] int32 j) L_0000: ldc.i4.0 L_0001: stloc.0 L_0002: ldloca.s j L_0003: call instance string [mscorlib]System.Int32::ToString() L_0004: call valuetype [system.Windows.Forms]System.Windows.Forms .DialogResult [system.Windows.Forms]System.Windows.Forms .MessageBox::Show(string) L_0005: pop L_0006: ret } So does the CLR itself zero out all variables? And therefore VB.NET is not really "doing anything", but instead is merely allowing the default behavior to occur, whereas C# is being more restrictive? Or is there a CIL setting, attribute, or the like somewhere that determines whether unassigned memory should be zeroed out before use automatically? (A setting that VB.NET would be using, but not C#?) Anyway, I was wondering if anyone here knew what was going on... Mike Quote Posting Guidelines Avatar by Lebb
Administrators PlausiblyDamp Posted April 13, 2008 Administrators Posted April 13, 2008 The actual initalisation is done in the .locals init ( [0] int32 j) bit. The runtime appears to always initialise variables, c# requires an explicit assignment before use though... In fact if you change the c# version to be int j = 0; then you get exactly what you expected. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
Mike_R Posted April 13, 2008 Author Posted April 13, 2008 Ok, thanks PD for clearing that up. :-) Funny, I had thought it was the other way around: that the CLR would not be taking extra steps like this and that VB.NET was "injecting code" to zero it out. Funny, then, that C# does not enforce field initializers? It would seem much easier to enforce that a field is initialized at the point of declaration (or within all constructors) than the complex path analysis that C# must undergo for variables? C# seems to be saying that it's ok to assume that a field will be the default null/0/false but it's not ok to assume the same for a variable? Anyway, thanks for solving this mystery for me, PD. One less thing keeping me up at night... :) Quote Posting Guidelines Avatar by Lebb
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.