gpt4 book ai didi

.net - ByRef 与 ByVal 会产生错误吗?

转载 作者:行者123 更新时间:2023-12-02 08:52:48 26 4
gpt4 key购买 nike

ByRefByVal 会生成错误!?

我有一个使用对象的方法

Function Foo(ByRef bar as CustomObject) as Boolean

此方法生成错误,因为一些奇怪的 .NET 运行时事物更改了 bar 对象,导致其 Dispose()al。

花了很多时间来理解这个事情(...对象被更改的地方),直到有人用 ByVal 替换 ByRef 并且对象不再更改当传递给这个方法时...

有人可以解释一下,会发生什么?

诺塔·贝尼(编辑)

正如在我的情况中,函数Foo确实不修改bar,不应该 ByRefByVal 具有相同效果吗?

Foo 刚刚从 bar 读取了属性。

代码:

Module Module1

Sub Main()
Dim b As New Bar
' see the output bellow '
Foo(b.Name)
Console.ReadLine()
End Sub

Function Foo(ByRef name As String) As Boolean
Console.WriteLine("Name is : '{0}'", name)
End Function

Class Bar
Private _Name As String = "John"

Property Name()
Get
Return _Name
End Get
Set(ByVal value)
If _Name IsNot Nothing Then
'_Name.Dispose() If this were an IDisposable, would have problems here'
End If
Console.WriteLine("Name is Changed to '{0}'", value)
End Set
End Property
End Class

End Module

输出:

Name is : 'John'
Name is Changed to 'John'

最佳答案

传递参数ByRef意味着如果有人为变量分配一个新值,该新值将被传递回调用函数。传递它时,ByVal 会将该值的副本传递给函数,因此更改不会传播回调用者。

请注意,当我引用时,它是实际存储在该变量中的内容。对于引用类型,这意味着它就是引用。 按值传递引用类型不会复制整个实例,而只是复制引用。这意味着对对象本身所做的任何更改对于调用函数仍然可见。

例如,假设我们有这个类:

Public Class Foo
Private m_Value as string

Public Property Value as String
Get
return m_Value
End Get
Set(Value as String)
m_Value = Value
End Set
End Property
End Class

在我们的程序中,我们有两个函数:

Public Sub DoWork(ByVal obj as Foo)
obj = Nothing
End Sub

Public Sub DoWorkRef(ByRef obj as Foo)
obj = Nothing
End Sub

我们这样调用它们:

Dim obj1 as new Foo()
Dim obj2 as new Foo()

obj1.Value = "bar"
obj2.Value = "baz"

DoWork(obj1)
DoWorkRef(obj2)

在此函数结束时,obj1 仍然有一个值,但 obj2 将是 Nothing。这是因为 obj1 是按值传递的,因此 DoWork 中的代码正在对该变量的副本进行操作(同样,它是同一个实例,只是 变量是不同的),而obj2是通过引用传递的,所以它指向与主代码相同的变量。

为了指出“同一实例”,假设我们将函数更改为如下所示:

Public Sub DoWork(ByVal obj as Foo)
obj.Value = "beep"
End Sub

Public Sub DoWorkRef(ByRef obj as Foo)
obj.Value = "bop"
End Sub

如果我们再次运行相同的代码,我们最终会发现 obj1.Value 等于“beep”,而 obj2.Value 也等于“beep”到“波普”。这是因为即使我们按值传递 obj1,该值也是一个引用。现在,您只有两个变量指向同一个实例,因此对该实例所做的任何操作都将反射(reflect)在这两个变量中。

要记住的重要一点是,当您为变量本身分配新值时,ByRefByVal 之间的唯一有效区别 。所有其他行为实际上都是相同的。

问题后编辑编辑

您没有将变量作为 ByRef 参数传递:您正在传递属性。虽然 C# 不允许这样做(因为这个问题),但 VB.NET 允许这样做。如果您将属性作为 ByRef 参数传递,则本质上就像这样做:

Dim _temp as String = b.Name
Foo(_temp)
b.Name = _temp

换句话说,当将属性作为 ByRef 参数传递时,该属性的 setter总是在执行函数后使用变量中存在的值来调用,即使值没有改变。

将属性作为 ByRef 参数传递是一个很好的经验法则。

关于.net - ByRef 与 ByVal 会产生错误吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2714101/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com