扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
VB.Net中模块定义的过程的默认访问级别是Public
创新互联始终坚持【策划先行,效果至上】的经营理念,通过多达十年累计超上千家客户的网站建设总结了一套系统有效的营销解决方案,现已广泛运用于各行各业的客户,其中包括:成都白乌鱼等企业,备受客户赞赏。
你可以使用ILDasm反汇编一个VB.Net程序来查看
我进行试验的源代码为(Console Application):
Module Module1
Sub Main()
k()
End Sub
Sub k()
Console.WriteLine("ABC")
Console.ReadLine()
End Sub
End Module
使用ILDasm进行反编译后
k()过程被解释为:
.method public static void k() cil managed
{
// 代码大小 20 (0x14)
.maxstack 8
IL_0000: nop
IL_0001: ldstr bytearray (C8 54 C8 54 ) // .T.T
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: call string [mscorlib]System.Console::ReadLine()
IL_0011: pop
IL_0012: nop
IL_0013: ret
} // end of method Module1::k
由此得知,在VB.NET的模块中定义的过程的默认访问级别是Public,而不是Friend
如果你在循环中定义的是值类型变量(如Integer、String等系统预定义的基本类型,以及用Structure定义的任何类型,如Point),那么是不会在循环的过程中不断地进行创建和销毁,这个要在ILDASM中看才会看到。你之所以在VB.NET中看到变量在循环外面就不见了,那是IDE在作怪,它根据调试信息屏蔽掉了。事实上这个变量在进入函数的时候就给你创建好了,并且在推出函数的时候才会被注销掉。
当然,以上的情况不包括用Class定义的所有类。例如Form、Control等。
建立这样一个ConsoleApplication,在Sub Main里面添加代码如下:
Public Sub Main()
Dim i As Integer
For i = 1 To 10
Dim s As String
s = i.ToString()
Next
End Sub
编译成Exe,然后执行VS.NET\Framework SDK\bin\目录下的ILDASM.EXE,用它打开编译好的EXE文件,找到Module1,双击Main:void(),就可以看到中间代码了——一种所谓IL的伪汇编。
再来给大家解释一下吧:
// method表示是“方法”,实际上就是函数。
// public和VB中的没区别,static表示是Shared的,void表示无返回值,cil表示是符合CIL的,managed 托管的。
method public static void Main() cil managed
{
.entrypoint //表示这里是整个程序的入口点。
//下面这个是一个标记,用于表示这个函数是单线程的。
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// Code size 23 (0x17)
.maxstack 2 //表示本地变量所需要的堆栈大小,2*4Bytes
.locals init ([0] int32 i, // init是初始化的意思,第0号整型本地变量i
[1] string s) // 第1号字符串变量s
IL_0000: nop // 空指令
IL_0001: ldc.i4.1 // 将整数(i4表示整数)1装入堆栈
IL_0002: stloc.0 // 将顶上的堆栈弹到第0号本地变量,也就是i中。
// 上面两句的意思是 (For) i = 1
IL_0003: ldloca.s i // 将本地变量i装到堆栈顶上。
//调用实例化(instance)的Int32.ToString()。(所有的返回值都在堆栈顶端)
IL_0005: call instance string [mscorlib]System.Int32::ToString()
IL_000a: stloc.1 // 将栈顶元素推到第1号本地变量,也就是s中。
//上面三句的意思是 s = i.ToString()
IL_000b: nop
IL_000c: ldloc.0 // 将i推到栈顶。
IL_000d: ldc.i4.1 // 将整数1推到栈顶。
IL_000e: add.ovf // 将堆栈最顶上的两个元素相加,并进行溢出检查。
IL_000f: stloc.0 // 将相加的结果(在栈顶)推到i中。
//上面三句的意思是 i = i 1
IL_0010: ldloc.0 // 将i推到栈顶
IL_0011: ldc.i4.s 10 // 将整数10推到栈顶。
IL_0013: ble.s IL_0003// 如果最顶上的两个元素中先入栈的小于等于后入栈的,
// 那就跳转到IL_0003
// 上面三句话的意思是 For (i=1) To 10 ... Next
IL_0015: nop
IL_0016: ret // 返回
} // end of method Module1::Main
于是,在整个循环过程中,只有最开始时有一个对s的初始化,其他地方就没有见到了,甚至没有看到显式的“注销”。这下子不用担心写在里面会降低效率了。
在VB.NET里,给变量赋值NoThing,其结果将对该变量赋予初始值;
而对于字符串变量初始值就是“”,数值变量初始值为0,布尔变量初始值为False。
所以对于字符串变量,赋予NoThing与赋予""是相同的。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流