Unomono
Unomono

Reputation: 326

How does a class member gets updated automatically in a Sub routine / function even if I pass in ByVal in VB.NET?

Can anyone help explain why the following will change a value in an object's member even if I pass it in ByVal?

Scenario: The name of the person is 'Sab' but when i pass the object in the sub routine, the name changes to 'John'.

I thought object types are passed in by reference only and should not be changed unless forced. Is this a feature in .NET and what is this behavior called?

Sub Main()
    Dim p As New Person
    p.name = "Sab"
    DoSomething(p)

    Console.WriteLine(p.name)                 ' John
    Console.Read()
End Sub

Public Sub DoSomething(ByVal p As Person)
    p.name = "John"
End Sub

Upvotes: 1

Views: 84

Answers (2)

Simon
Simon

Reputation: 14472

An instance of an object is a reference - it's a pointer to the object. If you pass any object by value, you are passing it's reference by value. Effectively, there is no difference in passing an object by value or by reference. .Net creates a new copy of the reference and passes it's value to your method but the new copy of the reference still points to the same object. Some folks say that "all objects are passed by reference" but this is not true, the reference to the object in the called method is NOT the same as the reference in the caller but they point to the same object.

If you really want to pass a copy of the object such that the called method may not modify the originals' properties, then you need to create a copy. See discussions about shallow vs deep copies and be careful to understand references to objects vs simple data types. Do think about your design though. It's rare to actually need to create a copy rather than a new object.

Upvotes: 1

Christian Hayter
Christian Hayter

Reputation: 31071

Writing to p.name is not the same as writing to p. ByVal prevents the parameter itself from being modified, e.g.

p = New Person

If you want to prevent the properties of Person from being written to, then you need to re-design the Person class to be immutable instead of mutable. Whether this is an appropriate thing to do depends on how you want your code to behave.

Example:

Public Class Person

    ' All fields are private
    Private _name As String

    ' All properties are read only
    Public ReadOnly Property Name As String
        Get
            Return _name
        End Get
    End Property

    ' Field values can *only* be set in the constructor
    Public Sub New(name As String)
        _name = name
    End Sub

End Class

Upvotes: 2

Related Questions