Why is it legal to pass ByRef "I" to VB.NET?

I was shocked just a minute ago to discover that the following is legal (the C # equivalent is definitely not):

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 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 

But which <strike> even a stranger is just as strange to me that he doesn’t seem to be doing what I expect:

 Dim a As New Assigner With {.Field = 10} a.AssignNew() Console.WriteLine(a.GetField()) 

The above outputs are "10", not "0", as I thought it would be (although, of course, this expectation was imposed by certain horror). It looks like you can pass Me ByRef , but the behavior is somehow overridden (?) ByVal Compiler as if you passed Me ByVal .

  • Why is it legal to pass Me ByRef ? (Is there any explanation for backward compatibility?)
  • Am I saying correctly that the behavior of this method is overridden by the compiler? If not, what am I missing?
+4
source share
4 answers

This behavior really follows quite straight from the Visual Basic specification.

11.4.3 Instance Expressions

An instance expression is the keyword Me , MyClass or MyBase . An instance expression that can only be used inside the body of a non-generic method, constructor, or property is classified as a value .

9.2.5.2 Reference parameters

If the type of the variable passed to the reference parameter is incompatible with the type of the referenced parameter, or if the variable is not passed as an argument to the referenced parameter , the temporary variable can be allocated and passed the reference parameter. The skipped value will be copied to the temporary variable before the method call and will be returned to the original variable (if any) when the method returns.

(All my attention)

So, the compiler will create a temporary variable assigned to the value Me , which will be passed as a ByRef parameter. Upon return, no copy of the resulting value will take place, since Me not a variable.

+5
source

It seems that the compiler converts "Me" into a variable, which is then passed to ByRef. If you compile your code and then open it with Reflector, you will see what happens:

 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 

It looks like this when you call AssignNew (), you assign a new instance to an internally generated variable. The variable "a" is not affected because it is not even part of the function.

+5
source

This is just one of thousands of possible “almost mistakes” that a programmer can make. MS caught most of them, in fact, sometimes I wonder how many warnings appear.

they missed this one.

How much he changes “me” is damn good! When you use the "I", it simply passes a copy of the real class you are working with for security purposes. If this worked the way you hoped, we will talk about the side effect of GIANT. You innocently work in the methods of your class, and their BAM suddenly you are in a TRUE other object! That would be awful! If you are going to do this, you can simply write a Sparetti MS-Basic code snippet with numbered all global steps, which are received randomly, and also not subs / functions.

The way this works is similar if you pass arguments in brackets. For example, this works as expected:

 Assign(Reference_I_Want_To_Set, New Assigner) 

But it does not change anything:

 Assign((Reference_I_Want_To_Set), New Assigner) 

If you reflect the above type of code, as adam101 suggests, you will see similar results. Although this is a huge disappointment in brackets, it is very good with Me !!!

+1
source

what you need to do to make this code work:

 Class Assigner ''// Ignore this for now. Private newPropertyValue As Integer Public Property NewProperty() As Integer Get Return newPropertyValue End Get Set(ByVal value As Integer) newPropertyValue = value End Set End Property ''// This part is not so weird... take another instance ByRef, ''// assign it to a different instance -- stupid but whatever. ' Shared Sub Assign(ByRef x As Assigner, ByVal y As Assigner) x = y End Sub ''// But... what this?!? Shared Sub AssignNew(ByRef x As Assigner) ''// Passing "Me" ByRef??? Assign(x, New Assigner) End Sub End Class 

then use it like

  Dim a As New Assigner With {.NewProperty = 10} Assigner.AssignNew(a) 

As far as I understand, you can’t change the link to the object while using it, so you need to change it in the general sub


since Me cannot be the purpose of the destination , the code seems to create a copy of it and from this point, your not using the real object, but its copy

0
source

All Articles