最佳实践:ByRef或ByVal?在.Net

时间:2008-11-14 14:12:21

标签: .net byref byval

在ByRef和ByVal之间进行选择时需要考虑的事项。

我理解两者之间的区别,但我不完全理解ByRef是否节省了资源,或者我们是否需要在.Net环境中担心这一点。

如果在某种情况下功能无关紧要,您如何在两者之间做出决定?

10 个答案:

答案 0 :(得分:34)

关于此,有很多错误信息。最重要的是,您了解difference between value types and reference typesdifference between pass by value and pass by reference

你几乎总是希望通过价值来传递。通过引用传递几乎总是“我希望返回多个结果,而不仅仅是通过将内容添加到传入的列表中”。使用pass-by-reference的方法的典型示例是Int32.TryParse,其中返回值是成功/失败,并且解析的值由out参数“返回”。

答案 1 :(得分:15)

对于所有类型,默认值为byValue,但重要的是要理解这两个选项对于“引用类型”(类)而不是值类型的含义。 (结构)。

对于引用类型,如果在方法中声明引用类型变量,则该变量是方法的堆栈帧中的内存位置。它不在堆上。初始化该变量时(使用new或factory,无论如何),您已在堆上创建了一个实际对象,该对象的地址存储在方法堆栈框架中声明的引用变量中。

当您将引用类型传递给另一个方法byVal时,您将创建存储在调用方法堆栈中的地址的副本,并将该值的副本(指针地址)传递给被调用的方法,并将其存储在被调用方法堆栈中的新内存槽。在被调用的方法中,新的克隆变量直接指向Heap上的同一个对象。因此,使用它可以更改同一对象的属性。但是您无法更改原始引用变量(在调用方法堆栈上)指向哪个堆对象。 如果,在我调用的方法中写了

  myVar = new object();

调用方法中的原始变量不会更改为指向新对象。

如果我传递一个引用类型byRef,otoh,我传递一个指向调用方法堆栈中声明的变量的指针(它包含指向堆上对象的指针)因此它是一个指向对象指针的指针。它指向调用方法堆栈上的内存位置,该堆栈指向堆上的对象 所以现在,如果我在被调用方法中更改变量的值,通过将其设置为新对象(),如上所述,因为它是对调用方法中的变量的“引用”,我实际上是在更改哪个对象调用方法中的变量指向。因此,在调用方法返回后,调用方法中的变量将不再指向堆上的同一原始对象。

答案 2 :(得分:8)

ByVal应该是您的“默认”。除非您有特殊原因要使用ByRef

,否则请使用它

答案 3 :(得分:8)

在.net中传递对象ByVal不会创建对象的副本,并且不会消耗更多的资源,然后ByRef,指针仍然传递给该函数。运行时只是确保您不能修改函数中的指针并为其返回不同的值。您仍然可以更改对象中的值,您将在函数外部看到这些更改。这就是为什么ByRef很少使用的原因。只有当你想要一个函数来改变回来的实际对象时才需要它;因此是一个输出参数。

答案 4 :(得分:5)

仅当参数为“output”参数时才使用“ByRef”。否则使用“ByVal”。对明确不应返回值的参数使用“ByRef”是危险的,并且很容易产生错误。

答案 5 :(得分:3)

我认为不应该使用ByRef - 这是一种不好的做法。我会将其应用于允许函数返回多个值的典型用例(通过ByRef参数)。函数返回包含多个返回值的结构化响应会更好。如果函数仅通过其return语句返回值,则更清晰,更明显。

答案 6 :(得分:0)

将某些参数标记为ByRef会向您的函数用户显示分配给该参数**的变量将被修改。****

如果对所有args使用ByRef ,则无法确定哪些变量被函数修改,哪些变量只是被它读取。 (除了在功能源内窥视!)

答案 7 :(得分:0)

根据Microsoft的说法,选择ByVal或ByRef可能会影响足够大的值的性能(请参阅Passing Arguments by Value and by Reference (Visual Basic)):

  

性能。虽然传递机制可以影响性能   你的代码,差异通常是微不足道的。一个例外   这是一个传递ByVal的值类型。在这种情况下,Visual Basic   复制参数的全部数据内容。因此,表示   大值类型如结构,可以更高效传递   它ByRef。

[强调补充]。

答案 8 :(得分:0)

Sub last_column_process()
Dim last_column As Integer

last_column = 234
MsgBox last_column

trying_byref x:=last_column
MsgBox last_column

trying_byval v:=last_column
MsgBox last_column

End Sub

Sub trying_byref(ByRef x)
x = 345
End Sub

Sub trying_byval(ByRef v)
v = 555
End Sub

答案 9 :(得分:0)

我会尝试简化很多混乱。你基本上有4个选择:

  1. 传递值类型byVal
  2. 传递值类型byRef
  3. 传递对象byVal
  4. 传递对象byRef
  5. 有些人说你应该从不使用byRef。虽然它们在技术上是正确的,但有一件事是肯定的。你应该从不使用 never 这个词。如果您从头开始设计系统,则应不惜一切代价避免使用byRef。使用它暴露了设计缺陷。但是,在现有系统上工作可能无法提供实现良好设计的灵活性。有时你必须做出结论,即使用byRef。例如,如果您可以使用byRef在2天内完成修复,则可以优先重新发明轮子并花一周的时间来获得相同的修复,以避免使用byRef。

    要点:

    1. 在值类型上使用byVal:将值传递给函数。这是首选方式 设计功能。
    2. 对值类型使用byRef:用于从函数返回多个值。如果你 正在创建一个需要返回多个值的函数 一个现有的系统,这可能比创建一个对象(以及设置属性和处理)更好 一个功能。
    3. 在对象上使用byVal:将对象的指针传递给函数。功能可以 修改对象。
    4. 在对象上使用byRef:将指向对象指针的指针传递给函数。允许 更改调用者指向的对象。这可能会导致一些 很难找到错误,我想不出任何有理由使用它。 不是说没有一个,但如果有的话很少 而且很远。