vb.net

位置:IT落伍者 >> vb.net >> 浏览文章

VB.NET循环体内的局部变量


发布日期:2021年03月30日
 
VB.NET循环体内的局部变量

我们知道在类或者结构初始化的时候 成员变量最好不要显式赋以NothingFalse等初值这样不但没有必要而且会降低性能因为成员变量首先会被分配内存空间并且该内存空间自动用进行初始化因此显式的赋值会增加指令操作而影响性能

但如果是局部变量呢?

一般情况下如果不显式初始化局部变量局部变量会被自动也赋以空值或者false

例如以下代码

Dim b As Boolean

ConsoleWriteLine(b)

Dim rnd As Random

If rnd Is Nothing Then

ConsoleWriteLine(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#不容许局部变量不显式初始化就开始使用编译器会提示错误无法编译

               

上一篇:VB.NET中监视文件夹的变化

下一篇:VB.NET中对象的克隆[2]