Hintergrund
Eigenschaften in Visual Basic ermöglichen die Kapselung von Logik zur Erlangung und Zuweisung von Werten. Mit der Einführung von Eigenschaften wird der Code lesbarer und sicherer, da der direkte Zugriff auf die Felder einer Klasse vermieden wird und die Implementierung von Validierungs- oder Berechnungslogik direkt in den Objekten erleichtert wird.
Problem
Einsteiger machen oft das Feld öffentlich oder verwenden automatische Eigenschaften ohne Getter/Setter mit enthaltenen Logiken, was zur Verletzung der Kapselung oder zur Unmöglichkeit führt, berechnete Werte zu implementieren. Ein weiteres Problem ist der rekursive Aufruf einer Eigenschaft innerhalb sich selbst, was zu einem StackOverflow führt.
Lösung
In Visual Basic wird ein privates Feld deklariert, und die Eigenschaft umfasst Get- und Set-Blöcke mit der erforderlichen Logik. Berechnete Eigenschaften verwenden nur Get, um einen berechneten Wert basierend auf privaten Feldern zurückzugeben. Im Set-Block sollte immer auf das private Feld zugegriffen werden, um eine endlose Rekursion zu vermeiden.
Beispiel Code:
Private _price As Decimal Private _quantity As Integer Public Property Total As Decimal Get Return _price * _quantity ' berechnete Eigenschaft End Get End Property Public Property Price As Decimal Get Return _price End Get Set(value As Decimal) If value < 0 Then Throw New ArgumentException("Preis muss positiv sein") _price = value End Set End Property
Schlüsselfunktionen:
Kann man innerhalb von Set Price auf die Eigenschaft Name zugreifen, wenn sie ebenfalls über ein privates Feld implementiert ist?
Ja, wenn im Set-Block der Eigenschaft Price auf eine andere Eigenschaft (z.B. Name) zugegriffen wird, ist das zulässig, da der Zugriff auf verschiedene private Felder keine Rekursion verursacht. Man sollte vermeiden, sich selbst zu referenzieren: Der Aufruf von Price innerhalb von Set Price würde eine Rekursion auslösen.
Beispiel Code:
Public Property Name As String Get Return _name End Get Set(value As String) _name = value End Set End Property Public Property Price As Decimal Get Return _price End Get Set(value As Decimal) If Name Is Nothing Then _name = "default" _price = value End Set End Property
Was passiert, wenn im Get-Block der Eigenschaft diese Eigenschaft erneut aufgerufen wird?
Das führt zu einer endlosen Rekursion und StackOverflow. Im Get-Block sollte immer das private Feld verwendet werden, ansonsten ruft sich die Eigenschaft selbst auf.
Public Property Amount As Decimal Get Return Amount ' führt zu endloser Rekursion End Get Set(value As Decimal) _amount = value End Set End Property
Kann man eine Eigenschaft nur zum Schreiben (WriteOnly) deklarieren und warum ist das gefährlich?
Es gibt WriteOnly-Eigenschaften, aber deren Verwendung wird nicht empfohlen, da das Objekt die Möglichkeit verliert, einen Wert zurückzugeben, was die Lesbarkeit und Vorhersehbarkeit verringert. Wenn sie nur zum Schreiben benötigt wird, sollte die Architektur überdacht werden.
Private _secret As String Public WriteOnly Property Secret As String Set(value As String) _secret = value ' Schreiben ist möglich, Lesen nicht. End Set End Property
Ein Programmierer entschied sich, das Feld Price öffentlich zu machen und direkt damit zu arbeiten. Infolgedessen wurde Price gelegentlich versehentlich negativ.
Vorteile:
Nachteile:
Ein Kollege ersetzte Price durch eine Eigenschaft mit einem privaten Feld und Validierung im Set-Block, was ungültige Werte verhinderte.
Vorteile:
Nachteile: