Limitazione dell'accessibilità delle funzioni di accesso (Guida per programmatori C#)
Le parti get e set di una proprietà o un indicizzatore sono denominate funzioni di accesso. Per impostazione predefinita, queste funzioni di accesso hanno la stessa visibilità o livello di accesso della proprietà o dell'indicizzatore a cui appartengono. Per altre informazioni, vedere Livelli di accessibilità. Tuttavia, è utile limitare l'accesso a una di queste funzioni di accesso. In genere, si limita l’accessibilità della funzione di accesso set
, mantenendo la funzione di accesso get
accessibile pubblicamente. Ad esempio:
private string _name = "Hello";
public string Name
{
get
{
return _name;
}
protected set
{
_name = value;
}
}
In questo esempio, una proprietà denominata Name
definisce una funzione di accesso get
e set
. La funzione di accesso get
riceve il livello di accessibilità della proprietà stessa, in questo caso public
, mentre la funzione di accesso set
è limitata in modo esplicito applicando il modificatore di accesso protected alla funzione di accesso stessa.
Nota
Gli esempi in questo articolo non usano proprietà implementate automaticamente. Le proprietà implementate automaticamente forniscono una sintassi concisa per dichiarare le proprietà quando non è necessario un campo sottostante personalizzato.
Restrizioni dei modificatori di accesso per le funzioni di accesso
L'uso dei modificatori delle funzioni di accesso nelle proprietà o negli indicizzatori è soggetto a queste condizioni:
- Non è possibile usare i modificatori delle funzioni di accesso su un'interfaccia o su un'implementazione esplicita di un membro interfaccia.
- È possibile usare i modificatori delle funzioni di accesso solo se la proprietà o l'indicizzatore ha entrambe le funzioni di accesso
set
eget
. In questo caso, il modificatore è consentito solo per una delle due funzioni di accesso. - Se la proprietà o l'indicizzatore ha un modificatore override, il modificatore della funzione di accesso deve corrispondere alla funzione di accesso della funzione di accesso sottoposta a override, se presente.
- Il livello di accessibilità nella funzione di accesso deve essere più restrittivo del livello di accessibilità nella proprietà o nell'indicizzatore stesso.
Modificatori di accesso per l'override di funzioni di accesso
Quando si esegue l'override di una proprietà o un indicizzatore, le funzioni di accesso sottoposte a override devono essere accessibili al codice di override. Inoltre, l'accessibilità della proprietà/indicizzatore e delle relative funzioni di accesso deve corrispondere alla proprietà/indicizzatore e alle funzioni di accesso sottoposti a override corrispondenti. Ad esempio:
public class Parent
{
public virtual int TestProperty
{
// Notice the accessor accessibility level.
protected set { }
// No access modifier is used here.
get { return 0; }
}
}
public class Kid : Parent
{
public override int TestProperty
{
// Use the same accessibility level as in the overridden accessor.
protected set { }
// Cannot use access modifier here.
get { return 0; }
}
}
Implementazione di interfacce
Quando si usa una funzione di accesso per implementare un'interfaccia, la funzione di accesso potrebbe non disporre di un modificatore di accesso. Se tuttavia si implementa l'interfaccia usando una sola funzione di accesso, ad esempio get
, l'altra funzione di accesso può avere un modificatore di accesso, come nell'esempio seguente:
public interface ISomeInterface
{
int TestProperty
{
// No access modifier allowed here
// because this is an interface.
get;
}
}
public class TestClass : ISomeInterface
{
public int TestProperty
{
// Cannot use access modifier here because
// this is an interface implementation.
get { return 10; }
// Interface property does not have set accessor,
// so access modifier is allowed.
protected set { }
}
}
Dominio di accessibilità della funzione di accesso
Se si usa un modificatore di accesso nella funzione di accesso, il dominio di accessibilità della funzione di accesso è determinato da questo modificatore.
Se non è stato usato un modificatore di accesso nella funzione di accesso, il dominio di accessibilità della funzione di accesso è determinato dal livello di accessibilità della proprietà o dell'indicizzatore.
Esempio
L'esempio seguente contiene tre classi, BaseClass
, DerivedClass
e MainClass
. Sono disponibili due proprietà per BaseClass
, Name
e Id
in entrambe le classi. L'esempio illustra come la proprietà Id
in DerivedClass
può essere nascosta dalla proprietà Id
in BaseClass
quando si usa un modificatore di accesso restrittivo, ad esempio protected o private. Pertanto, quando si assegnano valori a questa proprietà, viene invece chiamata la proprietà nella classe BaseClass
. La sostituzione del modificatore di accesso con public renderà la proprietà accessibile.
L'esempio illustra anche che un modificatore di accesso restrittivo, quale private
o protected
, nella funzione di accesso set
della proprietà Name
in DerivedClass
, impedisce l'accesso alla funzione di accesso nella classe derivata. Viene generato un errore quando lo si assegna o si accede alla proprietà della classe di base con lo stesso nome, se è accessibile.
public class BaseClass
{
private string _name = "Name-BaseClass";
private string _id = "ID-BaseClass";
public string Name
{
get { return _name; }
set { }
}
public string Id
{
get { return _id; }
set { }
}
}
public class DerivedClass : BaseClass
{
private string _name = "Name-DerivedClass";
private string _id = "ID-DerivedClass";
new public string Name
{
get
{
return _name;
}
// Using "protected" would make the set accessor not accessible.
set
{
_name = value;
}
}
// Using private on the following property hides it in the Main Class.
// Any assignment to the property will use Id in BaseClass.
new private string Id
{
get
{
return _id;
}
set
{
_id = value;
}
}
}
class MainClass
{
static void Main()
{
BaseClass b1 = new BaseClass();
DerivedClass d1 = new DerivedClass();
b1.Name = "Mary";
d1.Name = "John";
b1.Id = "Mary123";
d1.Id = "John123"; // The BaseClass.Id property is called.
System.Console.WriteLine("Base: {0}, {1}", b1.Name, b1.Id);
System.Console.WriteLine("Derived: {0}, {1}", d1.Name, d1.Id);
// Keep the console window open in debug mode.
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
}
/* Output:
Base: Name-BaseClass, ID-BaseClass
Derived: John, ID-BaseClass
*/
Commenti
Si noti che sostituendo la dichiarazione new private string Id
con new public string Id
, si otterrà l'output:
Name and ID in the base class: Name-BaseClass, ID-BaseClass
Name and ID in the derived class: John, John123