As a developer who thinks in C# but who works with VB from time to time, I tend not define if a parameter is ByRef or ByVal unless I have to.
I have also at times needed to describe why an application wasn?t breaking when I was assigning a value to an object?s property in a called function and that value was needed in the calling method, when the parameter did not have the keyword ByRef in the method signature.
The reason behind this is a fundamental part of .Net (and any developer who uses C# or VB should be aware of):
In .Net primitive types such as int, string, Boolean and a number of others are passed into a method by the value, while non-primitive types are passed in by their reference.
Look at the code below. After calling method1 only the car object?s values have been change because by default non-primitive types are passed by their reference, while the values of the int and the string have not been updated because only the values were passed into method.
For parameters which are passed in as values .Net Common Language Runtime (CLR) creates new variables for them within the scope of the method, once a method has finished the variables gets cleaned up and are lost.
After method2 the values of the int and the string were updated because the parameters were being passed in via their reference, hence in the VB code the keyword ?ByRef? and in C# ?ref?. The CLR will update the object which is being referenced, in this case the variables which are in the Main method scope.
VB Code
Sub Main Dim doorNumber As Integer = 88 Dim name As String = "Daniel" Dim car = New Car() car.Make = "Volkswagon" car.Model = "Polo" car.Year = 2016 Console.WriteLine("--- Call Method1 ---") Method1(doorNumber, name, car) Console.WriteLine(doorNumber)' 88 Console.WriteLine(name)' Daniel Console.WriteLine(car.ToString())' Make Volkswagon, Model Golf, Year 2016 Console.WriteLine("--- Call Method2 ---") Method2(doorNumber, name, car) Console.WriteLine(doorNumber)' 8 Console.WriteLine(name)' Michael Console.WriteLine(car.ToString())' Make Volkswagon, Model Golf, Year 2016 End Sub Private Sub Method1(doorNumber As Integer, name As String, car As Car) doorNumber = 8 name = "Michael" car.Model = "Golf" End Sub Private Sub Method2(ByRef doorNumber As Integer, ByRef name As String, car As Car) doorNumber = 8 name = "Michael" car.Model = "Golf" End Sub Public Class Car Public Property Make() As String Public Property Model() As String Public Property Year() As Integer Public Overrides Function ToString() As String Return String.Format("Make {0}, Model {1}, Year {2}", Make, Model, Year) End Function End Class
C#
void Main() { int doorNumber = 88; string name = "Daniel"; var car = new Car() { Make = "Volkswagon", Model = "Polo", Year = 2016 }; Console.WriteLine("--- Call Method1 ---"); Method1(doorNumber, name, car); Console.WriteLine(doorNumber); // 88 Console.WriteLine(name); // Daniel Console.WriteLine(car.ToString()); // Make Volkswagon, Model Golf, Year 2016 Console.WriteLine("--- Call Method2 ---"); Method2(ref doorNumber,ref name, car); Console.WriteLine(doorNumber); // 8 Console.WriteLine(name); // Michael Console.WriteLine(car.ToString()); // Make Volkswagon, Model Golf, Year 2016 } void Method1(int doorNumber, string name, Car car) { doorNumber = 8; name = "Michael"; car.Model = "Golf"; } void Method2(ref int doorNumber, ref string name, Car car) { doorNumber = 8; name = "Michael"; car.Model = "Golf"; } public class Car { public string Make { get; set; } public string Model { get; set; } public int Year { get; set; } public override string ToString() { return string.Format("Make {0}, Model {1}, Year {2}", Make,Model,Year); } } // Define other methods and classes here