Dan*_*Tao 4 vb.net compiler-construction byref this-pointer
刚才我震惊地发现以下是合法的(C#等价物绝对不是):
Class Assigner
''// Ignore this for now.
Public Field As Integer
''// This part is not so weird... take another instance ByRef,
''// assign it to a different instance -- stupid but whatever. '
Sub Assign(ByRef x As Assigner, ByVal y As Assigner)
x = y
End Sub
''// But... what's this?!?
Sub AssignNew()
''// Passing "Me" ByRef???
Assign(Me, New Assigner)
End Sub
''// This is just for testing.
Function GetField() As Integer
Return Me.Field
End Function
End Class
Run Code Online (Sandbox Code Playgroud)
但是,什么是更奇怪,就像我奇怪的是,它似乎并没有做什么,我希望:
Dim a As New Assigner With {.Field = 10}
a.AssignNew()
Console.WriteLine(a.GetField())
Run Code Online (Sandbox Code Playgroud)
以上输出"10",而非"0",就像我认为的那样(虽然很自然,这种期望本身也注入了某种恐怖).所以看起来你可以传递Me ByRef,但是编译器以某种方式覆盖(?)行为就好像你已经通过了一样Me ByVal.
Me ByRef?(是否有一些向后兼容性解释?)似乎编译器将"Me"转换为变量,然后传递ByRef.如果您编译代码,然后使用Reflector打开它,您可以看到发生了什么:
Class Assigner
''// Methods
Public Sub Assign(ByRef x As Assigner, ByVal y As Assigner)
x = y
End Sub
Public Sub AssignNew()
Dim VB$t_ref$S0 As Assigner = Me
Me.Assign((VB$t_ref$S0), New Assigner)
End Sub
Public Function GetField() As Integer
Return Me.Field
End Function
''// Fields
Public Field As Integer
End Class
Run Code Online (Sandbox Code Playgroud)
因此,当您调用AssignNew()时,您将新实例分配给内部生成的变量."a"变量不会被触及,因为它甚至不是函数的一部分.
这种行为实际上直接来自Visual Basic规范.
11.4.3实例表达式
实例表达式是关键字
Me,MyClass或MyBase.实例表达式(可能仅在非共享方法,构造函数或属性访问器的主体内使用)被归类为值.9.2.5.2参考参数
如果传递给引用参数的变量类型与引用参数的类型不兼容,或者将非变量作为参数传递给引用参数,则可以分配临时变量并将其传递给引用参数.传入的值将在调用方法之前复制到此临时变量中,并在方法返回时将其复制回原始变量(如果有).
(都强调我的)
因此,编译器将创建一个临时变量,该变量分配Me给要作为ByRef参数传递的值.返回时,不会产生结果值的副本,因为Me它不是变量.