扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
Friend过程快于Public过程
你可能会非常惊奇:Friend类型过程的执行速度要明显快于Public类型。这可以通过创建一个带有Private类和Public类 (设定Instancing = MultiUse)的ActiveX EXE工程看到,在2个类模块中添加下面的代码:
Public Sub PublicSub(ByVal value As Long)
’
End Sub
Public Function PublicFunction(ByVal value As Long) As Long
’
End Function
Friend Sub FriendSub(ByVal value As Long)
’
End Sub
Friend Function FriendFunction(ByVal value As Long) As Long
’
End Function
然后,在表单模块中创建一个循环,执行每个例程许多次。比如,要在一个Pentium II机器上查看执行时间上的区别,可以调用每个例程1,000,000次。下面是测试的结果:
Private类模块中,反复调用1,000,000次Public Sub或者Function耗费了0.46秒,而调用内容相同的Friend类型模块则分别只有0.05秒和0.06秒。前后竟然相差了8-9倍之多!对于MultiUse类型的Public类模块,也是一样的结果。
对于这个不可思议的结果的可能解释是:Friend型过程没有处理汇集和拆装代码的消耗(Public过程可以从当前工程外被调用,因此COM必须要来回地汇集数据)。
但是在多数情况下,这些时间差别是不明显的,特别是程序中包含一些复杂和耗时的语句时。
即使这样,Friend型过程仍有其他的优势高于Public类型,比如:接受和返回在BAS模块中定义的UDT变量的能力。
使用Objptr函数快速查找集合中的对象
ObjPtr函数的一个最简单但是却最有效的用途就是提供快速寻找集合中对象的关键字。假设有一个对象集合,它没有可以当做关键字以从集合中取回的属性。那么,我们就可以使用ObjPtr函数的返回值作为集合中的关键字:
Dim col As New Collection
Dim obj As CPerson
’创建新的CPerson对象,并添加到集合中
Set obj = New CPerson
obj.Name = "John Smith"
col.Add obj, CStr(ObjPtr(obj)) ’关键字必须是字符串
因为任何对象都有一个明确的ObjPtr数值,而且它是不变的,所以,我们可以容易地、快速地从集合中取回它:
’ 删除集合中的对象
col.Remove CStr(ObjPtr(obj))
这个技巧可以适用于任何类型的对象,包括VB中的表单和控件,以及外部对象。
使用ObjPtr检测2个对象变量是否指向同一对象
判断2个对象变量释放指向同一对象的方法是使用Is操作符,代码如下:
If obj1 Is obj2 Then ...
但当2个对象是同一类型时,或者指向同一个二级接口时,我们就可以利用ObjPtr()函数对代码进行一些优化处理:
If ObjPtr(obj1) = ObjPtr(obj2) Then ...
后者的执行速度将比前种方法快40%多。但是请注意,2种方法原本就是很有效率的,只有在时间要求非常严格的上百成千次的循环中,才会体现出这种差别。
读取文件内容的简洁方法
读取text文件的最快方法是使用Input$函数,就象下面的过程:
Function FileText (filename$) As String
Dim handle As Integer
handle = FreeFile
Open filename$ For Input As #handle
FileText = Input$(LOF(handle), handle)
Close #handle
End Function
使用上述方法要比使用Input命令读取文件每一行的方法快很多。下面是应用这个函数读取Autoexec.bat的内容到多行textbox控件的例子:
Text1.Text = FileText("c:\autoexec.bat")
但请注意:当文件包含Ctrl-Z(EOF)字符时,上面的函数代码可能会发生错误。因此,要修改一下代码:
Function FileText(ByVal filename As String) As String
Dim handle As Integer
’ 判断文件存在性
If Len(Dir$(filename)) = 0 Then
Err.Raise 53 ’文件没有找到
End If
’ 以binary模式打开文件
handle = FreeFile
Open filename$ For Binary As #handle
’ 读取内容,关闭文件
FileText = Space$(LOF(handle))
Get #handle, , FileText
Close #handle
End Function
字体对象克隆招法
当要应用一个控件的字体到另一控件时,最直接的方法就是直接赋值:
Set Text2.Font = Text1.Font
但多数情况下这种方法并不奏效,因为这实际上是将同一字体的引用分配给了2个控件。换言之,当随后修改其中之一控件的字体时,另外一个控件也受到影响。因此,要实现我们的目的,需要做的就是克隆字体对象并赋值给需要的控件。
最简单的克隆字体的方法是手工地拷贝所有单独的字体属性,就象下面一样:
Function CloneFont(Font As StdFont) As StdFont
Set CloneFont = New StdFont
CloneFont.Name = Font.Name
CloneFont.Size = Font.Size
CloneFont.Bold = Font.Bold
CloneFont.Italic = Font.Italic
CloneFont.Underline = Font.Underline
CloneFont.Strikethrough = Font.Strikethrough
End Function
’函数的应用
Set Text2.Font = CloneFont(Text1.Font)
如果使用VB6,就可以使用PropertyBag对象快速拷贝所有字体属性,并且代码会很简练、速度也快2倍:
Function CloneFont(Font As StdFont) As StdFont
Dim pb As New PropertyBag
’拷贝字体到PropertyBag对象中
pb.WriteProperty "Font", Font
’恢复字体对象到新控件
Set CloneFont = pb.ReadProperty("Font")
End Function
但是我们还能进一步地对代码进行优化,方法就是使用可被所有StdFont对象识别的隐藏IFont接口。这个接口具有一个Clone方法,用它就可以精确地实现我们的目的。它以非正常方式执行:创建一个克隆Font对象,然后返回相应的引用。这可能是实现克隆目的的最简洁代码了,而且,执行速度也是这里列举的3种方法中最快的一个,要比使用PropertyBag对象的方法快大约3倍左右。来看看具体代码:
Function CloneFont(Font As IFont) As StdFont
Font.Clone CloneFont
End Function
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者