VB.NET,是从函数引用返回的对象

时间:2011-08-05 20:40:20

标签: 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

如果我从其他地方调用此函数,它是否会在ret_obj中实例化该对象,然后创建一个深层副本以将副本传回给调用者,或者它只是传回一个引用?

3 个答案:

答案 0 :(得分:8)

这里有两个二分类问题,涉及相似的词汇:价值与参考类型,并按价值与参考传递变量

值v。参考类型

第一个问题是价值与参考类型。值类型通过复制传递 - 通常。值类型为:

  1. 日期
  2. 字符
  3. U / INT(16/32/64)
  4. 十进制
  5. 单人和双人
  6. 布尔
  7. 的Structs
  8. 枚举
  9. 除了上面列出的类型之外的所有类型都是引用类型。当一个对象被传递时,实际传递的是它的内存地址,通常被认为是32位平台上的int和64位平台上的长内存。


    按值传递<按参考

    第二个问题是通过值与参考传递变量

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

    按价值

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

    参考

    请记住,变量只是内存中用于保存内容的插槽。通过引用传递变量时,您将传递该槽的地址(而不是该槽中的数据)。

    如果该变量是值类型,则该槽本身保存值,因此传递的东西是指向该值的指针。

    如果该变量是引用类型,则插槽中存在指向对象在内存中的位置的指针,因此传递的东西是指向变量的指针(就像值类型一样),它本身包含另一个指针(不是像值类型一样,它导致保存变量引用的对象的内存位置。

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

    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更改为指向新对象。但它仍然可以通过设置字段和属性并调用其方法来更改对象。

    按参考方式返回?

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

    总而言之,当您从函数返回一个对象时,唯一复制的是对象的地址。从函数返回值类型时,将复制值本身。

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

答案 1 :(得分:7)

它只传回一个引用(假设big_obj是一个类)。我不会在这里使用术语“引用”,因为在参数传递方面它具有微妙的不同含义 - 但假设big_obj是一个类 - 引用类型 - ret_obj的值是一个引用,该引用将是返回的内容。

从VB的角度来看,我没有这方面的任何文章,但是如果你很高兴看到C#,你会发现这些文章很有用:

答案 2 :(得分:0)

VB.NET没有能力通过引用返回。 C#也没有,但它一直是proposed。你实际得到的只是对象的引用。因此,要精确定义它,会向对象返回一个引用。它不会通过引用返回,就像您可以与ByRef关键字进行比较一样。