In C #, the equivalent code will not compile .. NET is not comfortable passing properties by reference, for reasons why people like Eric Lippert have gone elsewhere (I vaguely recall that Eric turned to this question regarding C # where something on SO, but cannot find it now - this will require one strange workaround or another, all of which have flaws that the C # team considers unacceptable).
VB does this, but as a rather strange special case: the behavior that I see is what I would expect if it would create a temporary variable that is passed by reference, and then assigns its value to the property after the method is completed. This is a workaround (confirmed by Eric Lippert himself in the comments below, see also the wonderful @Martin Verjans answer) with side effects that contradict each other who doesn't know how byref
/ ref
implemented in .NET.
When you think about it, they cannot make it work properly, because VB.NET and C # (both F #, IronPython, etc.) must be mutually compatible, so the VB byref
parameter must be compatible with the argument C # ref
passed from C # code. Therefore, any workaround should be fully responsible for the call. Within common sense, this limits him to what he can do before the start of the call, and after his return.
Here the ECMA 335 standard (Common Language Infrastructure) should say ( Ctrl + F search for byref
"):
& sect; I.8.2.1.1 Managed Pointers and Associated Types
A managed pointer (ยงI.12.1.1.2) or byref (ยงI.8.6.1.3, ยงI.12.4.1.5.2) can specify a local variable, parameter, field of a composite type, or an array element ....
In other words, for the compiler, ByRef storage As T
is actually the address of the storage location in memory where the code places the value. It is very effective at runtime, but does not offer the possibility of syntactic sugar magic with getters and setters. A property is a pair of methods, a getter and a setter (or just one or the other, of course).
So, as you describe, storage
gets a new value inside SetProperty()
, and after SetProperty()
completes, _text1.Text
has a new value. But the compiler introduced some occult frauds that lead to the fact that the actual sequence of events will not be what you expect.
As a result, SetProperty
cannot be used in Text1
in the way you wrote it. The simplest solution that I checked is to call OnPropertyChanged()
directly in the installer for Text1
.
Public Property Text1 As String Get Return _text1.Text End Get Set(ByVal value As String) _text1.Text = value Me.OnPropertyChanged() End Set End Property
There is no way to handle this, which is at least a little ugly. You can give Text1
correct support field, for example Text2
, but then you will need to synchronize it with _text1.Text
. This is uglier than the previous IMO, because you have to synchronize the two, and you still have additional code in the Text1
installer.