To jest przypadek nieszczelnej abstrakcji. Właściwość jest w rzeczywistości metodą, metody dostępu get i set dla indeksatora są kompilowane do metod get_Index () i set_Index. Kompilator wykonuje świetną robotę ukrywając ten fakt, automatycznie tłumaczy przypisanie do właściwości na przykład na odpowiednią metodę set_Xxx ().
Ale to idzie do góry nogami, gdy przekażesz parametr metody przez odniesienie. Wymaga to od kompilatora JIT przekazania wskaźnika do lokalizacji pamięci przekazanego argumentu. Problem w tym, że takiego nie ma, przypisanie wartości właściwości wymaga wywołania metody ustawiającej. Wywołana metoda nie może odróżnić przekazanej zmiennej od przekazanej właściwości i dlatego nie może wiedzieć, czy wywołanie metody jest wymagane.
Godne uwagi jest to, że to faktycznie działa w VB.NET. Na przykład:
Class Example
Public Property Prop As Integer
Public Sub Test(ByRef arg As Integer)
arg = 42
End Sub
Public Sub Run()
Test(Prop) '' No problem
End Sub
End Class
Kompilator VB.NET rozwiązuje ten problem, automatycznie generując ten kod dla metody Run, wyrażony w języku C #:
int temp = Prop;
Test(ref temp);
Prop = temp;
Które obejście można również zastosować. Nie do końca wiem, dlaczego zespół C # nie zastosował tego samego podejścia. Prawdopodobnie dlatego, że nie chcieli ukrywać potencjalnie kosztownych wywołań getter i setter. Lub całkowicie niezdiagnozowalne zachowanie, które otrzymasz, gdy ustawiacz ma efekty uboczne, które zmieniają wartość właściwości, znikną po przypisaniu. Klasyczna różnica między C # a VB.NET, C # to „bez niespodzianek”, a VB.NET to „zrób to, jeśli możesz”.