VB.NET循环体内的局部变量
我們知道,在類或者結構初始化的時候, 成員變量最好不要顯式賦以0、Nothing、False等初值,這樣不但沒有必要而且會降低性能。因為成員變量首先會被分配內存空間,并且該內存空間自動用“0”進行初始化,因此顯式的賦值會增加指令操作而影響性能。
但如果是局部變量呢?
一般情況下,如果不顯式初始化局部變量,局部變量會被自動也賦以空值、0、或者false。
'例如以下代碼
????????Dim?b?As?Boolean
????????Console.WriteLine(b)
????????Dim?rnd1?As?Random
????????If?rnd1?Is?Nothing?Then
????????????Console.WriteLine("yes")
????????End?If
'最終會輸出:"false?yes"
?不過對于引用類型的Random,編譯器會給出“ 變量“rnd1”在賦值前被使用。可能會在運行時導致 null 引用異常。”? 的警告。值類型則沒有任何警告。
ok,再來看下這段代碼:
Code?1Module?Module1Module?Module1
?2
?3????Sub?Main()Sub?Main()
?4????????Dim?rnd?As?New?Random(1000)
?5????????For?i?As?Integer?=?0?To?4
?6????????????Dim?b?As?Boolean
?7????????????Console.WriteLine(b)
?8????????????If?rnd.NextDouble?>?0.5?Then
?9????????????????b?=?True
10????????????End?If
11????????Next
12????End?Sub
13
14End?Module
Module?Module1
????Sub?Main()
????????Dim?rnd?As?New?Random(1)
????????For?i?As?Integer?=?0?To?9
????????????Dim?b?As?Boolean
????????????Console.WriteLine(b)
????????????If?rnd.NextDouble?<?0.5?Then
????????????????b?=?True
????????????End?If
????????Next
????????For?i?As?Integer?=?0?To?9
????????????Dim?rnd1?As?Random
????????????If?rnd1?Is?Nothing?Then
????????????????Console.WriteLine("yes")
????????????Else
????????????????Console.WriteLine("no")
????????????End?If
????????????rnd1?=?New?Random
????????Next
????End?Sub
End?Module
照說每次循環都重新定義并初始化該局部變量,期望的輸出值應該一直都是false。
但猜猜實際最終輸出結果是什么,false,false,false,true,true!!
就是這個怪誕的行為讓我困擾了很久。
ok,我們看看對應的il代碼:
Code.method?public?static?void?Main()?cil?managed
{
????.custom?instance?void?[mscorlib]System.STAThreadAttribute::.ctor()
????.entrypoint
????.maxstack?2
????.locals?init?(
????????[0]?class?[mscorlib]System.Random?rnd,
????????[1]?bool?b,
????????[2]?int32?i,
????????[3]?bool?VB$CG$t_bool$S0,
????????[4]?int32?VB$CG$t_i4$S0,
????????[5]?int32?num)
????L_0000:?nop?
????L_0001:?ldc.i4?0x3e8
????L_0006:?newobj?instance?void?[mscorlib]System.Random::.ctor(int32)
????L_000b:?stloc.0?
????L_000c:?ldc.i4.0?
????L_000d:?stloc.2?
????L_000e:?ldloc.1?
????L_000f:?call?void?[mscorlib]System.Console::WriteLine(bool)
????L_0014:?nop?
????L_0015:?ldc.i4.1?
????L_0016:?stloc.1?
????L_0017:?nop?
????L_0018:?ldloc.2?
????L_0019:?ldc.i4.1?
????L_001a:?add.ovf?
????L_001b:?stloc.2?
????L_001c:?ldloc.2?
????L_001d:?ldc.i4.4?
????L_001e:?stloc.s?num
????L_0020:?ldloc.s?num
????L_0022:?ble.s?L_000e
????L_0024:?ldc.i4.0?
????L_0025:?stloc.s?VB$CG$t_i4$S0
????L_0027:?ldloc.3?
????L_0028:?call?void?[mscorlib]System.Console::WriteLine(bool)
????L_002d:?nop?
????L_002e:?ldc.i4.1?
????L_002f:?stloc.3?
????L_0030:?nop?
????L_0031:?ldloc.s?VB$CG$t_i4$S0
????L_0033:?ldc.i4.1?
????L_0034:?add.ovf?
????L_0035:?stloc.s?VB$CG$t_i4$S0
????L_0037:?ldloc.s?VB$CG$t_i4$S0
????L_0039:?ldc.i4.4?
????L_003a:?stloc.s?num
????L_003c:?ldloc.s?num
????L_003e:?ble.s?L_0027
????L_0040:?nop?
????L_0041:?ret?
}
?
?
暈......編譯器居然自動把變量b聲明提升到循環體之外......因此就出現了上述的行為。(注:暈啊,以前學c的時候,就學過for(;;){int i=5;}里,i只在第一次聲明,以前的基礎知識全部忘光光。感謝psic的指正。)
我個人猜測,編譯器這樣做的原因大概是為了性能。可是這樣實在是容易造成奇異的行為,最郁悶的是,值類型的變量,編譯器根本連警告都沒有。
所以,VB.NET中使用局部變量,尤其在循環體內使用局部變量,一定要進行初始化。
PS:這個話題在c#里就沒有任何意義了。c#不容許局部變量不顯式初始化就開始使用,編譯器會提示錯誤無法編譯。
轉載于:https://www.cnblogs.com/NewCivil/archive/2009/05/02/1447743.html
總結
以上是生活随笔為你收集整理的VB.NET循环体内的局部变量的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Web开发] 微软的 PHP+IIS+
- 下一篇: iptables 智能限速方案