在ByRef和ByVal之间进行选择时需要考虑的事项。
我理解两者之间的区别,但我不完全理解ByRef是否节省了资源,或者我们是否需要在.Net环境中担心这一点。
如果在某种情况下功能无关紧要,您如何在两者之间做出决定?
答案 0 :(得分:34)
关于此,有很多错误信息。最重要的是,您了解difference between value types and reference types和difference 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个选择:
有些人说你应该从不使用byRef。虽然它们在技术上是正确的,但有一件事是肯定的。你应该从不使用 never 这个词。如果您从头开始设计系统,则应不惜一切代价避免使用byRef。使用它暴露了设计缺陷。但是,在现有系统上工作可能无法提供实现良好设计的灵活性。有时你必须做出结论,即使用byRef。例如,如果您可以使用byRef在2天内完成修复,则可以优先重新发明轮子并花一周的时间来获得相同的修复,以避免使用byRef。
要点: