ByRef vs ByVal澄清

Bra*_*rad 18 vb.net byref byval

我刚刚开始一个类来处理与TCP服务器的客户端连接.这是我到目前为止编写的代码:

Imports System.Net.Sockets
Imports System.Net

Public Class Client
    Private _Socket As Socket

    Public Property Socket As Socket
        Get
            Return _Socket
        End Get
        Set(ByVal value As Socket)
            _Socket = value
        End Set
    End Property

    Public Enum State
        RequestHeader ''#Waiting for, or in the process of receiving, the request header
        ResponseHeader ''#Sending the response header
        Stream ''#Setup is complete, sending regular stream
    End Enum

    Public Sub New()

    End Sub

    Public Sub New(ByRef Socket As Socket)
        Me._Socket = Socket

    End Sub
End Class
Run Code Online (Sandbox Code Playgroud)

所以,在我的重载构造函数上,我接受对a 的实例引用,是吗?System.Net.Sockets.Socket

现在,在我的Socket财产上,设置值时,必须是ByVal.我的理解是复制内存中的实例,并将这个新实例传递给我,并且我的代码设置为在内存中引用此实例.是?value_Socket

如果这是真的,那么我不明白为什么我会想要使用除了本机类型之外的任何属性.我想如果复制具有大量成员的类实例会有相当大的性能损失.此外,特别是对于这个代码,我想象一个复制的套接字实例不会真正起作用,但我还没有测试过它.

无论如何,如果你能够证实我的理解,或者解释我迷雾逻辑中的缺陷,我将非常感激.

Jar*_*Par 47

我认为你混淆了引用与价值类型和ByVal对比的概念ByRef.尽管他们的名字有点误导,但它们是正交问题.

ByVal在VB.NET中意味着将提供的值的副本发送到该函数.对于值类型(Integer,Single等),这将提供值的浅表副本.对于较大的类型,这可能是低效的.对于引用类型(String,类实例),传递引用的副本.因为副本通过突变传递给参数,=所以调用函数不会看到它.

ByRef在VB.NET中意味着对原始值的引用将被发送到函数(1).它几乎就像在函数中直接使用原始值.类似的操作=会影响原始值并在调用函数中立即可见.

Socket是一个引用类型(读取类),因此传递它ByVal是便宜的.即使它确实执行了复制,它也是引用的副本,而不是实例的副本.

(1)这不是100%正确,因为VB.NET实际上在调用点支持几种ByRef.有关更多详细信息,请参阅博客条目ByRef的许多案例


  • +1 - '我认为你混淆了引用与值类型和ByVal与ByRef的概念.尽管名称有点误导,但它们是正交问题.',来自C++,这让我失望. (2认同)

Joe*_*orn 12

请记住,ByVal仍然传递参考.不同之处在于您获得了参考文献的副本.

所以,在我的重载构造函数上,我接受对System.Net.Sockets.Socket实例的引用,是吗?

是的,但如果您要求它,情况也是如此ByVal.不同之处在于,ByVal您获得了参考文献的副本 - 您有新的变量.有ByRef,它是相同的变量.

据我所知,内存中的实例被复制了

不.仅复制参考.因此,您仍在使用相同的实例.

这是一个代码示例,可以更清楚地解释它:

Public Class Foo
   Public Property Bar As String
   Public Sub New(ByVal Bar As String)
       Me.Bar = Bar
   End Sub
End Class

Public Sub RefTest(ByRef Baz As Foo)
     Baz.Bar = "Foo"
     Baz = new Foo("replaced")
End Sub

Public Sub ValTest(ByVal Baz As Foo)
    Baz.Bar = "Foo"
    Baz = new Foo("replaced")
End Sub

Dim MyFoo As New Foo("-")
RefTest(MyFoo)
Console.WriteLine(MyFoo.Bar) ''# outputs replaced

ValTest(MyFoo)
Console.WriteLine(MyFoo.Bar) ''# outputs Foo
Run Code Online (Sandbox Code Playgroud)