ser*_*hio 2 .net vb.net .net-2.0
ByRefvs ByVal生成错误!?
我有一个使用Object的方法
Function Foo(ByRef bar as CustomObject) as Boolean
Run Code Online (Sandbox Code Playgroud)
这个方法生成错误,因为一些奇怪的.NET运行时事物改变了bar对象,导致其Dispose()al.
花了很多时间来理解这个东西(......对象被改变的地方),直到有人替换ByRef为ByVal和对象在传递给这个方法时不再改变...
有人可以解释一下,会发生什么?
正如在我的情况的功能Foo并不会修改bar,不应该ByRef还是ByVal有同样的效果呢?
在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
Run Code Online (Sandbox Code Playgroud)
输出:
名称是:'John'
名称更改为'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
Run Code Online (Sandbox Code Playgroud)
在我们的程序中,我们有两个功能:
Public Sub DoWork(ByVal obj as Foo)
obj = Nothing
End Sub
Public Sub DoWorkRef(ByRef obj as Foo)
obj = Nothing
End Sub
Run Code Online (Sandbox Code Playgroud)
我们称它们为:
Dim obj1 as new Foo()
Dim obj2 as new Foo()
obj1.Value = "bar"
obj2.Value = "baz"
DoWork(obj1)
DoWorkRef(obj2)
Run Code Online (Sandbox Code Playgroud)
在这个函数的最后,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
Run Code Online (Sandbox Code Playgroud)
如果我们再次运行相同的代码,我们最终obj1.Value将等于"嘟嘟",并obj2.Value等于"bop".这是因为即使我们obj1通过值传递,该值也是一个参考.您现在只有两个变量指向同一个实例,因此完成的任何操作都将反映在两个变量中.
要记住的重要一点是,当您为变量本身分配新值时,ByRef和之间唯一有效的区别ByVal.所有其他行为实际上是相同的.
后问题编辑编辑
您没有将变量作为ByRef参数传递:您正在传递属性.虽然C#不允许这样(因为这个问题),VB.NET会允许它.如果您将属性作为ByRef参数传递,它实际上就像这样做:
Dim _temp as String = b.Name
Foo(_temp)
b.Name = _temp
Run Code Online (Sandbox Code Playgroud)
换句话说,当将属性作为ByRef参数传递时,即使值未更改,也始终使用执行函数后变量中存在的值调用该属性的setter .
不将属性作为ByRef参数传递是一个很好的经验法则.
| 归档时间: |
|
| 查看次数: |
384 次 |
| 最近记录: |