Storia della domanda
Le proprietà in Visual Basic consentono di incapsulare la logica di ottenimento e assegnazione dei valori. Con l'introduzione delle proprietà, il codice diventa più leggibile e sicuro, eliminando la necessità di accesso diretto ai campi della classe e facilitando l'inserimento di logica di validazione o calcolo direttamente negli oggetti.
Problema
I principianti spesso rendono un campo pubblico o utilizzano proprietà automatiche senza getter/setter contenenti logica, il che porta a violazioni dell'incapsulamento o all'impossibilità di implementare valori calcolati. Un altro problema è la chiamata ricorsiva della proprietà all'interno di se stessa, che porta a StackOverflow.
Soluzione
In Visual Basic si dichiara un campo privato, e la proprietà include i blocchi Get e Set con la logica necessaria. Le proprietà calcolate utilizzano solo Get, restituendo un valore calcolato basato sui campi privati. All'interno del blocco set, è sempre necessario fare riferimento al campo privato per evitare la ricorsione infinita.
Esempio di codice:
Private _price As Decimal Private _quantity As Integer Public Property Total As Decimal Get Return _price * _quantity ' proprietà calcolata 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("Il prezzo deve essere positivo") _price = value End Set End Property
Caratteristiche chiave:
È possibile accedere alla proprietà Name all'interno di Set Price se anche essa è implementata tramite un campo privato?
Sì, se nel blocco set della proprietà Price si accede a un'altra proprietà (ad esempio, Name), questo è consentito, poiché i riferimenti a diversi campi privati non causano ricorsione. È necessario evitare di riferirsi a se stessi: la chiamata a Price all'interno di Set Price causerà ricorsione.
Esempio di codice:
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
Cosa succede se nel blocco Get della proprietà si richiama nuovamente questa proprietà?
Questo porterà a una ricorsione infinita e a StackOverflow. Nel blocco get è sempre necessario utilizzare il campo privato, altrimenti la proprietà si richiamerà da sola.
Public Property Amount As Decimal Get Return Amount ' porterà a ricorsione infinita End Get Set(value As Decimal) _amount = value End Set End Property
È possibile dichiarare una proprietà solo in scrittura (WriteOnly) e quali sono i rischi?
Esistono proprietà WriteOnly, ma non è consigliabile usarle, poiché l'oggetto perde la capacità di restituire un valore, il che riduce la leggibilità e la prevedibilità. Se è necessaria solo per la scrittura, è meglio rivedere l'architettura.
Private _secret As String Public WriteOnly Property Secret As String Set(value As String) _secret = value ' È possibile scrivere, ma non ricevere. End Set End Property
Un programmatore ha deciso di rendere il campo Price pubblico e ha lavorato direttamente con esso. Di conseguenza, Price diventava occasionalmente negativo per errore.
Pro:
Contro:
Un collega ha sostituito Price con una proprietà con un campo privato e validazione nel blocco set, prevenendo valori non corretti.
Pro:
Contro: