我自己都忘记从哪里看到这条“准则”了,而且一直深信不疑,虽然觉得在循环体外声明一个只有在循环体内才会用到的变量,使代码看起来非常的不优雅——因为我好像还记得有另一条“原则”:尽量使局部变量的作用域最小化。
这条“准则”背后的理由,大概就是如果在循环体里定义变量,每次循环后就会被重新定义,带来额外开销......然而我在实际中发现情况并非如此,因此就困惑地写了篇想当然的随笔。
被一位朋友回复指正错误纠正了的理解错误后,结合实际中的代码,我开始怀疑起这条“不要在循环体内定义对象”的准则来。搜索了一下,发现了两篇有意思的讨论,见这里和这里。 顺便发现,和我犯一样错误的人也不在少数啊^_^
最关键的地方在于,对局部变量的声明和定义的理解。
函数(过程)中的所有局部变量,都是在函数刚开始时被声明,而不是在声明语句(vb中是dim语句)出现的位置才声明。至于变量的定义,“As 子句后接等号 (=),等号后接变量的初始值。Visual Basic 每次运行 Dim 语句时都将此指定值赋给变量。如果不指定初始值,则 Visual Basic 首次进入包含 Dim 语句的代码时,会将变量的数据类型的默认初始值赋给变量。”——引自MSDN:如何:创建新变量。
用一段代码来解释就是:
dim b1 as boolean
dim b2 as boolean = true
Next
' 实际完全等效于下面的代码
dim b1,b2 as boolean
For i as int32 = 0 to 9
b2 = true
Next
这样,我上一篇中的疑惑算是彻底消除了。晕啊,基础知识啊基础知识。
但等等,再看这段代码:
Dim b(k-1) As Boolean
For j As Integer = 0 To k -1
Console.Write(b(j))
b(j) = True
Next
Console.WriteLine()
Next
Module Module1
Sub Main()
For i As Integer = 0 To 1
Dim b(1) As Boolean
For j As Integer = 0 To 1
Console.Write(b(j))
Next
b(1) = True
Console.WriteLine()
Next
End Sub
End Module
嗯,按照前面的分析,该代码相当于:
For i As Integer = 0 To n - 1
For j As Integer = 0 To k -1
Console.Write(b(j))
b(j) = True
Next
Console.WriteLine()
Next
显而易见,结果应该是除了第一行是false之外;满屏都是true。但实际输出却是满屏false,囧.....
好吧,其实这涉及到数组的声明和初始化的语法。
' 实际相当于:
dim b() as boolean = new boolean (k - 1 ){}
另外上面的代码,的确涉及到了一个“不要在循环体中×××”的准则,看代码:
For i As Integer = 0 To n - 1
Dim b(k) As Boolean ' 重新初始化数组
' .这里执行其他操作
Next
' 应该替换成以下写法
Dim b(k) As Boolean
For i As Integer = 0 To n - 1
Array.clear(b, 0 ,b.length) ' 重新初始化数组
' .这里执行其他操作
Next
就这些了。
PS:开始觉得vb有点让人不爽了,如果是c#应该没有这些困惑......
odule Module1
Sub Main()
Dim b(1) As Boolean
For i As Integer = 0 To 1
For j As Integer = 0 To 1
Console.Write(b(j))
Next
b(1) = True
Console.WriteLine()
Next
End Sub
End Module
'显而易见,此代码输出是:false,true;false,true