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, a volte è utile limitare l'accesso a una di queste funzioni di accesso. In genere, si limita l'accessibilità della funzione di accesso, mantenendo get la funzione di set accesso 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 di questo articolo non usano proprietà implementate automaticamente. Le proprietà implementate automaticamente forniscono una sintassi concisa per dichiarare le proprietà quando non è necessario un campo di backup 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 della funzione di accesso in un'interfaccia o in un'implementazione esplicita del membro dell'interfaccia .
  • È possibile usare i modificatori delle funzioni di accesso solo se la proprietà o l'indicizzatore ha entrambe le funzioni di accesso set e get. 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 dimostra anche che un modificatore di accesso restrittivo, ad esempio private o , nella set funzione di accesso della proprietà DerivedClass in impedisce l'accesso alla funzione di Name accesso nella protectedclasse derivata. Genera un errore quando lo si assegna o accede alla proprietà della classe di base dello 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

Vedi anche