我們知道在類或者結構初始化的時候 成員變量最好不要顯式賦以NothingFalse等初值這樣不但沒有必要而且會降低性能因為成員變量首先會被分配內存空間並且該內存空間自動用進行初始化因此顯式的賦值會增加指令操作而影響性能
但如果是局部變量呢?
一般情況下如果不顯式初始化局部變量局部變量會被自動也賦以空值或者false
例如以下代碼
Dim b As Boolean
Console
WriteLine(b)
Dim rnd
As Random
If rnd
Is Nothing Then
Console
WriteLine(
yes
)
End If
最終會輸出false yes
不過對於引用類型的Random編譯器會給出 變量rnd在賦值前被使用可能會在運行時導致 null 引用異常 的警告值類型則沒有任何警告
ok再來看下這段代碼
Module ModuleModule Module
Sub Main()Sub Main()
Dim rnd As New Random()
For i As Integer = To
Dim b As Boolean
ConsoleWriteLine(b)
If rndNextDouble > Then
b = True
End If
Next
End Sub
End Module
Module Module
Sub Main()
Dim rnd As New Random()
For i As Integer = To
Dim b As Boolean
ConsoleWriteLine(b)
If rndNextDouble < Then
b = True
End If
Next
For i As Integer = To
Dim rnd As Random
If rnd Is Nothing Then
ConsoleWriteLine(yes)
Else
ConsoleWriteLine(no)
End If
rnd = New Random
Next
End Sub
End Module
照說每次循環都重新定義並初始化該局部變量期望的輸出值應該一直都是false
但猜猜實際最終輸出結果是什麼falsefalsefalsetruetrue!!
就是這個怪誕的行為讓我困擾了很久
ok我們看看對應的il代碼
method public static void Main() cil managed
{
custom instance void [mscorlib]SystemSTAThreadAttribute::ctor()
entrypoint
maxstack
locals init (
[] class [mscorlib]SystemRandom rnd
[] bool b
[] int i
[] bool VB$CG$t_bool$S
[] int VB$CG$t_i$S
[] int num)
L_: nop
L_: ldci xe
L_: newobj instance void [mscorlib]SystemRandom::ctor(int)
L_b: stloc
L_c: ldci
L_d: stloc
L_e: ldloc
L_f: call void [mscorlib]SystemConsole::WriteLine(bool)
L_: nop
L_: ldci
L_: stloc
L_: nop
L_: ldloc
L_: ldci
L_a: addovf
L_b: stloc
L_c: ldloc
L_d: ldci
L_e: stlocs num
L_: ldlocs num
L_: bles L_e
L_: ldci
L_: stlocs VB$CG$t_i$S
L_: ldloc
L_: call void [mscorlib]SystemConsole::WriteLine(bool)
L_d: nop
L_e: ldci
L_f: stloc
L_: nop
L_: ldlocs VB$CG$t_i$S
L_: ldci
L_: addovf
L_: stlocs VB$CG$t_i$S
L_: ldlocs VB$CG$t_i$S
L_: ldci
L_a: stlocs num
L_c: ldlocs num
L_e: bles L_
L_: nop
L_: ret
}
暈編譯器居然自動把變量b聲明提升到循環體之外因此就出現了上述的行為(注暈啊以前學c的時候就學過for(;;){int i=;}裡i只在第一次聲明以前的基礎知識全部忘光光感謝psic的指正)
我個人猜測編譯器這樣做的原因大概是為了性能可是這樣實在是容易造成奇異的行為最郁悶的是值類型的變量編譯器根本連警告都沒有
所以VBNET中使用局部變量尤其在循環體內使用局部變量一定要進行初始化
PS這個話題在c#裡就沒有任何意義了c#不容許局部變量不顯式初始化就開始使用編譯器會提示錯誤無法編譯
From:http://tw.wingwit.com/Article/program/net/201311/15512.html