Utilizzo delle proprietà (Guida per programmatori C#)
Le proprietà combinano gli aspetti sia dei campi che dei metodi. Per l'utente di un oggetto, una proprietà sembra essere un campo; l'accesso alla proprietà richiede la stessa sintassi. Per l'implementatore di una classe, una proprietà è uno o due blocchi di codice, che rappresentano una get
funzione di accesso e/o una set
funzione di accesso o init
. Il blocco di codice per la get
funzione di accesso viene eseguito quando la proprietà viene letta. Il blocco di codice per la set
funzione di accesso o init
viene eseguito quando alla proprietà viene assegnato un valore. Una proprietà senza una funzione di accesso set
viene considerata di sola lettura. Una proprietà senza una funzione di accesso get
viene considerata di sola scrittura. Una proprietà con entrambe le funzioni di accesso è di lettura/scrittura. È possibile usare una init
funzione di accesso anziché una set
funzione di accesso per abilitare l'impostazione della proprietà come parte dell'inizializzazione degli oggetti, ma in caso contrario renderla di sola lettura.
A differenza dei campi, le proprietà non vengono classificate come variabili. Pertanto, non è possibile passare una proprietà come ref
parametro o out
.
Le proprietà hanno molti usi:
- Possono convalidare i dati prima di consentire una modifica.
- Possono esporre in modo trasparente i dati in una classe in cui tali dati vengono recuperati da un'altra origine, ad esempio un database.
- Possono eseguire un'azione quando i dati vengono modificati, ad esempio la generazione di un evento o la modifica del valore di altri campi.
Le proprietà sono dichiarate nel blocco della classe specificando il livello di accesso del campo, seguito dal tipo della proprietà, seguito dal nome della proprietà, seguito da un blocco di codice che dichiara una funzione di accesso get
e/o una funzione di accesso set
. Ad esempio:
public class Date
{
private int _month = 7; // Backing store
public int Month
{
get => _month;
set
{
if ((value > 0) && (value < 13))
{
_month = value;
}
}
}
}
In questo esempio, Month
è dichiarato come una proprietà in modo che la funzione di accesso set
possa verificare che il valore Month
sia compreso tra 1 e 12. La proprietà Month
usa un campo privato per tenere traccia del valore effettivo. La posizione reale dei dati di una proprietà viene spesso definita "archivio di backup" della proprietà. È comune che le proprietà usino campi privati come archivio di backup. Il campo viene contrassegnato come privato per assicurare che possa essere modificato solo chiamando la proprietà. Per altre informazioni sulle restrizioni di accesso pubblico e privato, vedere Modificatori di accesso. Le proprietà implementate automaticamente forniscono una sintassi semplificata per le dichiarazioni di proprietà semplici. Per altre informazioni, vedere Proprietà implementate automaticamente.
Funzione di accesso get
Il corpo della funzione di accesso get
è simile a quello di un metodo. Deve restituire un valore del tipo di proprietà. Il compilatore C# e il compilatore JIT rilevano modelli comuni per l'implementazione della get
funzione di accesso e ottimizzano tali modelli. Ad esempio, una get
funzione di accesso che restituisce un campo senza eseguire alcun calcolo è probabilmente ottimizzata per una lettura di memoria di tale campo. Le proprietà implementate automaticamente seguono questo modello e traggono vantaggio da queste ottimizzazioni. Tuttavia, non è possibile inlinizzare un metodo della funzione di accesso virtuale get
perché il compilatore non sa in fase di compilazione quale metodo potrebbe effettivamente essere chiamato in fase di esecuzione. Nell'esempio seguente viene illustrata una get
funzione di accesso che restituisce il valore di un campo _name
privato :
class Employee
{
private string _name; // the name field
public string Name => _name; // the Name property
}
Quando si fa riferimento alla proprietà, tranne che come destinazione di un'assegnazione, viene chiamata la funzione di accesso get
per leggere il valore della proprietà. Ad esempio:
var employee= new Employee();
//...
System.Console.Write(employee.Name); // the get accessor is invoked here
La get
funzione di accesso deve essere un membro con corpo di espressione o terminare in un'istruzione return o throw e il controllo non può passare dal corpo della funzione di accesso.
Avviso
Si tratta di uno stile di programmazione non valido per modificare lo stato dell'oggetto usando la get
funzione di accesso.
La funzione di accesso get
può essere usata per restituire il valore del campo o per calcolarlo e restituirlo. Ad esempio:
class Manager
{
private string _name;
public string Name => _name != null ? _name : "NA";
}
Nell'esempio precedente, se non si assegna un valore alla Name
proprietà , restituisce il valore NA
.
Funzione di accesso set
La funzione di accesso set
è simile a un metodo il cui tipo restituito è void. Usa un parametro implicito denominato value
, il cui tipo è il tipo della proprietà. Il compilatore e il compilatore JIT riconoscono anche i modelli comuni per una set
funzione di accesso o init
. Questi modelli comuni sono ottimizzati, scrivendo direttamente la memoria per il campo sottostante. Nell'esempio seguente, viene aggiunta una funzione di accesso set
alla proprietà Name
:
class Student
{
private string _name; // the name field
public string Name // the Name property
{
get => _name;
set => _name = value;
}
}
Quando si assegna un valore alla proprietà, viene richiamata la funzione di accesso set
tramite un argomento che fornisce il nuovo valore. Ad esempio:
var student = new Student();
student.Name = "Joe"; // the set accessor is invoked here
System.Console.Write(student.Name); // the get accessor is invoked here
È un errore usare il nome del parametro implicito, value
, per una dichiarazione di variabile locale in una set
funzione di accesso.
Funzione di accesso init
Il codice per creare una init
funzione di accesso è uguale al codice per creare una set
funzione di accesso, ad eccezione del fatto che si usa la init
parola chiave anziché set
. La differenza è che la init
funzione di accesso può essere usata solo nel costruttore o usando un inizializzatore di oggetto.
Osservazioni:
Le proprietà possono essere contrassegnate come public
, protected
private
, internal
, protected internal
, o private protected
. Questi modificatori di accesso definiscono in che modo gli utenti della classe possono accedere alla proprietà. Le get
funzioni di accesso e set
per la stessa proprietà possono avere modificatori di accesso diversi. Ad esempio, get
potrebbe essere public
consentire l'accesso in sola lettura dall'esterno del tipo e set
può essere private
o protected
. Per altre informazioni, vedere Modificatori di accesso.
Una proprietà può essere dichiarata come proprietà statica usando la static
parola chiave . Le proprietà statiche sono disponibili per i chiamanti in qualsiasi momento, anche se non esiste alcuna istanza della classe. Per altre informazioni, vedere Classi statiche e membri di classi statiche.
Una proprietà può essere contrassegnata come proprietà virtuale usando la parola chiave virtual . Le proprietà virtuali consentono alle classi derivate di eseguire l'override del comportamento della proprietà usando la parola chiave override . Per altre informazioni su queste opzioni, vedere Ereditarietà.
Una proprietà che esegue l'override di una proprietà virtuale può anche essere sealed, specificando che per le classi derivate non è più virtuale. Infine, una proprietà può essere dichiarata astratta. Le proprietà astratte non definiscono un'implementazione nella classe e le classi derivate devono scrivere la propria implementazione. Per altre informazioni su queste opzioni, vedere Classi e membri delle classi astratte e sealed.
Nota
È un errore usare un modificatore virtual, abstract o override in una funzione di accesso di una proprietà statica.
Esempi
Questo esempio illustra le proprietà di istanza, statiche e di sola lettura. Accetta il nome del dipendente dalla tastiera, incrementa NumberOfEmployees
di 1 e visualizza il nome e il numero del dipendente.
public class Employee
{
public static int NumberOfEmployees;
private static int _counter;
private string _name;
// A read-write instance property:
public string Name
{
get => _name;
set => _name = value;
}
// A read-only static property:
public static int Counter => _counter;
// A Constructor:
public Employee() => _counter = ++NumberOfEmployees; // Calculate the employee's number:
}
Esempio di proprietà hidden
In questo esempio viene illustrato come accedere a una proprietà in una classe di base nascosta da un'altra proprietà con lo stesso nome in una classe derivata:
public class Employee
{
private string _name;
public string Name
{
get => _name;
set => _name = value;
}
}
public class Manager : Employee
{
private string _name;
// Notice the use of the new modifier:
public new string Name
{
get => _name;
set => _name = value + ", Manager";
}
}
class TestHiding
{
public static void Test()
{
Manager m1 = new Manager();
// Derived class property.
m1.Name = "John";
// Base class property.
((Employee)m1).Name = "Mary";
System.Console.WriteLine("Name in the derived class is: {0}", m1.Name);
System.Console.WriteLine("Name in the base class is: {0}", ((Employee)m1).Name);
}
}
/* Output:
Name in the derived class is: John, Manager
Name in the base class is: Mary
*/
Di seguito sono riportati gli aspetti più importanti relativi all'esempio precedente:
- La proprietà
Name
nella classe derivata nasconde la proprietàName
nella classe di base. In tal caso, viene usato il modificatorenew
nella dichiarazione della proprietà nella classe derivata:public new string Name
- Il cast
(Employee)
viene usato per accedere alla proprietà nascosta nella classe di base:((Employee)m1).Name = "Mary";
Per altre informazioni su come nascondere i membri, vedere Modificatore new.
Esempio di proprietà di override
In questo esempio, due classi, Cube
e Square
, implementano una classe astratta, Shape
, ed eseguono l'override della proprietà astratta Area
. Si noti l'uso del modificatore override nelle proprietà. Il programma accetta il lato come input e calcola le aree per il quadrato e il cubo. Inoltre, accetta l'area come input e calcola il lato corrispondente per il quadrato e il cubo.
abstract class Shape
{
public abstract double Area
{
get;
set;
}
}
class Square : Shape
{
public double side;
//constructor
public Square(double s) => side = s;
public override double Area
{
get => side * side;
set => side = System.Math.Sqrt(value);
}
}
class Cube : Shape
{
public double side;
//constructor
public Cube(double s) => side = s;
public override double Area
{
get => 6 * side * side;
set => side = System.Math.Sqrt(value / 6);
}
}
class TestShapes
{
static void Main()
{
// Input the side:
System.Console.Write("Enter the side: ");
double side = double.Parse(System.Console.ReadLine());
// Compute the areas:
Square s = new Square(side);
Cube c = new Cube(side);
// Display the results:
System.Console.WriteLine("Area of the square = {0:F2}", s.Area);
System.Console.WriteLine("Area of the cube = {0:F2}", c.Area);
System.Console.WriteLine();
// Input the area:
System.Console.Write("Enter the area: ");
double area = double.Parse(System.Console.ReadLine());
// Compute the sides:
s.Area = area;
c.Area = area;
// Display the results:
System.Console.WriteLine("Side of the square = {0:F2}", s.side);
System.Console.WriteLine("Side of the cube = {0:F2}", c.side);
}
}
/* Example Output:
Enter the side: 4
Area of the square = 16.00
Area of the cube = 96.00
Enter the area: 24
Side of the square = 4.90
Side of the cube = 2.00
*/
Vedi anche
Commenti e suggerimenti
https://aka.ms/ContentUserFeedback.
Presto disponibile: Nel corso del 2024 verranno gradualmente disattivati i problemi di GitHub come meccanismo di feedback per il contenuto e ciò verrà sostituito con un nuovo sistema di feedback. Per altre informazioni, vedereInvia e visualizza il feedback per