Vb.net 是通过引用从函数返回的对象

Vb.net 是通过引用从函数返回的对象,vb.net,deep-copy,shallow-copy,return-by-reference,Vb.net,Deep Copy,Shallow Copy,Return By Reference,这应该是一个相当常见的问题,但我还没有找到一个简单的答案 如果我在VB.NET中实例化一个函数中的对象并返回它,它是通过引用还是通过值返回它。IE-如果我写这样的东西,我是否应该担心性能: Public Function ret_obj_func() As big_object Dim ret_obj As New big_obj(<lots of stuff>) Return ret_obj End Function Sub IPassByReference

这应该是一个相当常见的问题,但我还没有找到一个简单的答案

如果我在VB.NET中实例化一个函数中的对象并返回它,它是通过引用还是通过值返回它。IE-如果我写这样的东西,我是否应该担心性能:

Public Function ret_obj_func() As big_object
    Dim ret_obj As New big_obj(<lots of stuff>)
    Return ret_obj
End Function
Sub IPassByReference
   Dim myVariable As Boolean = False
   IReceiveByReference myVariable
   Debug.Print(myVariable.ToString()) 'Always prints True
End Function

Sub IReceiveByReference(ByRef flag As Boolean)
   flag = True 'the memory address of myVariable was passed.
End Function
公共函数ret_obj_func()作为大对象
Dim ret_obj作为新的big_obj()
返回ret_obj
端函数

如果我从其他地方调用此函数,它会实例化ret_obj中的对象,然后创建一个深度副本以将副本传递回调用方,还是只传递回引用?

它只传递回引用(假设
big_obj
是一个类)。我不会在这里使用术语“by reference”,因为当涉及到参数传递时,它有着微妙的不同含义-但是假设
big_obj
是一个类-一个引用类型-
ret_obj
的值是一个引用,该引用将是返回的

从VB的角度来看,我没有任何关于这方面的文章,但如果您乐于了解C#,您可能会发现这些文章很有用:


VB.NET无法通过引用返回。C#也不这么认为,但事实一直如此。你实际得到的只是对对象的引用。因此,为了精确地定义它,它将返回对对象的引用。它不会像您可能比较的
ByRef
关键字那样通过引用返回。

这里有两个类似词汇表的二分法问题:值与引用类型,以及通过值传递变量与通过引用传递变量

价值。参考类型 第一个问题是值与引用类型的比较。值类型通常通过复制传递。值类型包括:

  • 日期
  • 煤焦
  • U/Int(16/32/64)
  • 十进制
  • 单人和双人
  • 布尔值
  • 结构
  • 列举
  • 除上面列出的类型外,所有类型都是引用类型。当一个对象被传递时,实际上传递的是它的内存地址,在32位平台上通常被认为是int,在64位平台上被认为是long


    通过值v传递。参照 第二个问题是通过值与引用传递变量

    变量是内存中某个位置上的一个插槽,它可以容纳内容。对于值类型,它保存实际值。对于引用类型,它保存堆上对象的内存地址(或为空)

    按值计算

    当您按值传递变量时,该变量的内存位置上的任何内容都将被复制。对于值类型,这意味着复制值本身。对于引用类型,复制的是变量引用的对象的内存地址

    参考

    请记住,变量只是内存中用来存放内容的插槽。通过引用传递变量时,传递的是该插槽的地址(与该插槽中的数据相反)

    如果该变量是一个值类型,则该槽保存该值本身,因此传递的对象是指向该值的指针

    如果该变量是引用类型,则插槽中包含一个指向对象在内存中位置的指针,因此传递的对象是指向变量的指针(与值类型类似),该变量本身包含另一个指针(与值类型不同),该指针指向保存该变量引用的对象的内存位置

    这允许函数修改另一个函数中的变量,如下所示:

    Public Function ret_obj_func() As big_object
        Dim ret_obj As New big_obj(<lots of stuff>)
        Return ret_obj
    End Function
    
    Sub IPassByReference
       Dim myVariable As Boolean = False
       IReceiveByReference myVariable
       Debug.Print(myVariable.ToString()) 'Always prints True
    End Function
    
    Sub IReceiveByReference(ByRef flag As Boolean)
       flag = True 'the memory address of myVariable was passed.
    End Function
    
    让我们比较一下按值传递的情况:

    Sub IPassByValue
       Dim myVariable As Boolean = False
       IReceiveByValue myVariable 
       Debug.Print(myVariable.ToString()) 'Always prints False
    End Function
    
    Sub IReceiveByValue(ByVal flag As Boolean)
       flag = True 'the value of myVariable was passed.
    End Function
    
    在上面的示例中,Boolean是一种值类型。如果它是一个对象,IReceiveByReference将有权将myVariable指向一个全新的对象,因为它接收myVariable的地址,而不是myVariable指向的对象的地址。相比之下,IReceiveByValue只传递myVariable的内容,因此它无法将myVariable更改为指向新对象。不过,它仍然可以通过设置对象的字段和属性并调用其方法来更改对象

    通过引用返回?

    虽然函数可以通过引用传递变量,但不能以这种方式返回变量。当函数返回时,其局部变量不再存在(或者如果它们是堆分配的,则等待清理)。因此函数总是按值返回;由于局部变量不再具有有效的内存地址,因此没有任何要返回的变量引用

    综上所述,当您从函数返回对象时,唯一被复制的是对象的地址。从函数返回值类型时,将复制值本身


    这意味着引用类型本质上是值类型,其中值是堆上某个对象的内存地址(或无)。

    是否将
    大对象定义为类或结构?