I encountered an interesting case where pass-by-reference does not appear to work in VB.NET. I've supplied some sample code below for you all to play with. Can anyone explain this phenomenon. Is this intended, or a bug with the language/compiler?
What I am seeing with this code is that the "After Increment" read-out is the same as the "Before Increment" readout.
Public Class Wrapper
Public Property Value As Integer
End Class
Sub Main()
Dim rand As New Random()
Dim w As New Wrapper()
w.Value = rand.Next()
Console.WriteLine("Before Increment: {0}", w.Value)
Try
Increment(w.Value)
Catch ex As Exception
End Try
Console.WriteLine("After Increment: {0}", w.Value)
Console.ReadLine()
End Sub
Public Sub Increment(ByRef i As Integer)
i += 1
Throw New Exception()
End Sub
Passing value objects by reference is in general a bad design. There are certain scenarios it's valid for, like array position swapping for high performance sorting operations. There are very few reasons you should need this functionality. In C# the usage of the OUT keyword is generally a shortcoming in and of itself.
In . NET Framework, all objects are by default passed by value not passed by reference either it is a Value Type (so called Primitive types like int, char, double, etc.) or Reference Type (class, interface, delegate, string, etc.).
The major disadvantages of using call by reference method are a follows: A function taking in a reference requires ensuring that the input is non-null. Thus, a null check is not supposed to be made. Thus, it has a non-null guarantee. Further, passing by reference makes the function not pure theoretically.
In C#, arguments can be passed to parameters either by value or by reference. Remember that C# types can be either reference types ( class ) or value types ( struct ): Pass by value means passing a copy of the variable to the method. Pass by reference means passing access to the variable to the method.
I encountered an interesting case where pass-by-reference does not appear to work in VB.NET.
Indeed, this is quite an interesting case.
I've supplied some sample code below for you all to play with. Can anyone explain this phenomenon.
Yes.
Is this intended, or a bug with the language/compiler?
This behaviour is by design and it is not a bug. You should not write VB code like this. If it hurts when you do this, stop doing it.
This all makes sense, but you have to understand the logic of it. Follow along
Try
Dim Temp As Integer
Temp = w.Value ' copy-in
Increment(Temp) ' make an alias to Temp
w.Value = Temp ' copy-out
Catch ex As Exception
End Try
Now it should be obvious why your program has the behaviour that it does. The throw happens before the copy-out.
People often say that C# and VB are "the same language" with different syntax, and there is some truth to that. However, examples that show small differences illustrate that the languages have different design principles. It is not an accident that C# and VB differ in their treatment of values passed by ref!
Design principles of C# include that the compiler should tell you when the code looks wrong and in particular the compiler should not "paper over" problems by guessing what you meant, and emitting code to kinda-sorta make it work most of the time. The design team sees the attitude of C# programmers as "the compiler is my friend who tells me when I'm wrong so I can improve".
Design principles of VB include that the code probably works just fine, and that if there's something that looks not quite right, figure out what the user meant and make it work, even if that means introducing code that, say, doesn't preserve object identity, or adds a hidden copy-in-copy-out or whatever. The design teams sees the attitude of VB programmers as "the compiler too often stands in my way; I've expressed an intention so make it work".
Both design principles are entirely sensible and there are large developer constituencies for each. I think it is quite nice that Microsoft has spent decades doubling the expense of language development so that developers have the ability to choose a language that suits their temperaments.
That said: there are situations in C# where the compiler will do something similar: create a temporary variable, assign a value to it, and then pass the variable by ref.
Challenge: create a program which demonstrates this fact.
Hint #1: mutable structs are a bad practice in C# for a reason.
Hint #2: under what circumstances is a variable treated as a value in C#?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With