在VB.NET中,哪个更快用于方法参数,ByVal
或者ByRef
?
此外,它在运行时(RAM)消耗更多资源?
我仔细阅读了这个问题,但答案不适用或不够具体.
Byval和ByRef参数应该根据它们如何工作而不是速度的要求和知识来使用.
http://www.developer.com/net/vb/article.php/3669066
回应斯劳的评论 -
哪个在运行时消耗更多资源?
参数在堆栈上传递.堆栈非常快,因为它的内存分配只是一个指针增量,用于保留新的"帧"或"分配记录".大多数.NET参数都不超过机器寄存器的大小,如果使用任何"堆栈"空间来传递参数那么少.实际上,基本类型和指针都在堆栈上分配..NET中的堆栈大小限制为1 MB.这可以让您了解参数传递消耗的资源很少.
您可能会发现这一系列文章很有趣:
通过堆栈分配提高性能(.NET内存管理:第2部分)
哪个更快?ByVal或ByRef.
根据你的测量环境,很难准确地测量和精灵测量,但是我写了一个基准,用一个方法调用了1亿次,得出以下结论:
参考类型 - 通过ByRef:420毫秒
参考类型 - 通过ByVal:382 ms
值类型 - 通过ByRef:421 ms
值类型 - 通过ByVal:416毫秒
Public Sub Method1(ByRef s As String) Dim c As String = s End Sub Public Sub Method2(ByVal s As String) Dim c As String = s End Sub Public Sub Method3(ByRef i As Integer) Dim x As Integer = i End Sub Public Sub Method4(ByVal i As Integer) Dim x As Integer = i End Sub Sub Main() Dim s As String = "Hello World!" Dim k As Integer = 5 Dim t As New Stopwatch t.Reset() t.Start() For i As Integer = 0 To 100000000 Method1(s) Next t.Stop() Console.WriteLine("Reference Type - ByRef " & t.ElapsedMilliseconds) t.Reset() t.Start() For i As Integer = 0 To 100000000 Method2(s) Next t.Stop() Console.WriteLine("Reference Type - ByVal " & t.ElapsedMilliseconds) t.Reset() t.Start() For i As Integer = 0 To 100000000 Method3(i) Next t.Stop() Console.WriteLine("Value Type - ByRef " & t.ElapsedMilliseconds) t.Reset() t.Start() For i As Integer = 0 To 100000000 Method4(i) Next t.Stop() Console.WriteLine("Value Type - ByVal " & t.ElapsedMilliseconds) Console.ReadKey() End Sub
在每种方法中注释掉变量和赋值 -
参考类型 - 通过ByRef:389 ms
参考类型 - 通过ByVal:349毫秒
值类型 - 通过ByRef:416毫秒
值类型 - 通过ByVal:385毫秒
可以得出结论,传递引用类型(字符串,类)ByVal将节省一些时间.您可能还会说传递值类型(整数,字节) - ByVal将节省一些时间.
在宏伟的计划中,时间可以忽略不计.更重要的是正确使用ByVal和ByRef并了解"幕后"的情况.在您的例程中实现的算法肯定会多次影响程序的运行时间.
如果您使用的是非常大的值类型(例如,Guid非常大),通过引用传递参数可能会稍微快一点.在其他情况下,当您通过引用传递而不是按值传递时可能会有更多复制等 - 例如,如果您有一个字节参数,那么一个字节明显少于指针在您使用的四个或八个字节通过引用传递它.
在实践中,你几乎不应该担心这一点.尽可能编写最易读的代码,这几乎总是意味着通过值而不是引用传递参数.我很少使用ByRef.
如果您想提高性能并认为ByRef会对您有所帮助,请在提交之前仔细地(根据您的具体情况)对其进行基准测试.
编辑:我在评论中注意到另一个(以前接受的,现在删除的)答案,关于ByRef vs ByVal在价值类型方面的含义存在很多误解.我有一篇关于参数传递的文章,这篇文章多年来已经证明是流行的 - 它是在C#术语中,但同样的概念适用于VB.NET.
这取决于.如果要传递一个对象,它已经传递了一个指针.这就是为什么如果你传入一个ArrayList(例如)并且你的方法将一些东西添加到ArrayList,那么调用代码也有相同的对象进入它的ArrayList,传入,因为它是相同的ArrayList.它没有传递指针的唯一时间是将具有内部数据类型的变量(如int或double)传递给函数.此时,它会创建一个副本.但是,这些对象的数据大小非常小,在内存使用或执行速度方面几乎没有任何区别.
如果传入引用类型,则ByRef较慢.
这是因为传入的是指向指针的指针.对对象上的字段的任何访问都需要取消引用额外的指针,这将需要几个额外的时钟周期才能完成.
如果传递值类型,那么如果结构有许多成员,则byref可能会更快,因为它只传递单个指针而不是复制堆栈上的值.在访问成员方面,byref会更慢,因为它需要进行额外的指针取消引用(sp-> pValueType-> member vs sp-> member).
在VB中大多数时候你不必担心这一点.
在.NET中,很少有具有大量成员的值类型.它们通常很小.在这种情况下,传入值类型与向过程传递多个参数没有什么不同.例如,如果您有按值传递Point对象的代码,则它的perf将与将X和Y值作为参数的方法相同.看到DoSomething(x为整数,y为整数)可能不会导致perf问题.事实上,你可能永远不会三思而后行.
如果您要定义自己的大值类型,那么您应该重新考虑将它们转换为引用类型.
唯一的另一个区别是执行代码所需的指针间接数量的增加.您很少需要在该级别进行优化.大多数情况下,您可以解决算法问题,或者您的性能瓶颈与IO相关,例如等待数据库或写入文件,在这种情况下,消除指针间接对您没有多大帮助.
因此,我不建议您应该专注于为您提供所需语义的内容,而不是专注于byter byval或byref更快.一般来说,除非你特别需要byref,否则最好使用byval.它使程序更容易理解.