Ograniczanie dostępności metody dostępu (Przewodnik programowania w języku C#)

Pobieranie i ustawianie części właściwości lub indeksatora są nazywane metodami dostępu. Domyślnie te metody dostępu mają ten sam poziom widoczności lub dostępu właściwości lub indeksatora, do którego należą. Aby uzyskać więcej informacji, zobacz poziomy ułatwień dostępu. Jednak czasami przydatne jest ograniczenie dostępu do jednego z tych metod dostępu. Zazwyczaj można ograniczyć dostępność set metody dostępu, zachowując get dostęp do metody dostępu publicznie. Na przykład:

private string _name = "Hello";

public string Name
{
    get
    {
        return _name;
    }
    protected set
    {
        _name = value;
    }
}

W tym przykładzie właściwość o nazwie Name definiuje metodę get i set metodę dostępu. Akcesorium get otrzymuje poziom ułatwień dostępu samej właściwości, w tym przypadku, public podczas gdy set akcesorium jest jawnie ograniczone przez zastosowanie modyfikatora dostępu chronionego do samego dostępu.

Uwaga

Przykłady w tym artykule nie używają właściwości implementowanych automatycznie. Właściwości zaimplementowane automatycznie zapewniają zwięzłą składnię deklarowania właściwości, gdy niestandardowe pole kopii zapasowej nie jest wymagane.

Ograniczenia dotyczące modyfikatorów dostępu dla metod dostępu

Używanie modyfikatorów dostępu we właściwościach lub indeksatorach podlega następującym warunkom:

  • Modyfikatory dostępu nie mogą być używane w interfejsie ani w implementacji jawnej składowej interfejsu .
  • Modyfikatory dostępu można używać tylko wtedy, gdy właściwość lub indeksator ma zarówno metody dostępu, jak set i get . W takim przypadku modyfikator jest dozwolony tylko na jednym z dwóch metod dostępu.
  • Jeśli właściwość lub indeksator ma modyfikator przesłonięcia , modyfikator dostępu musi być zgodny z akcesorem przesłoniętego dostępu, jeśli istnieje.
  • Poziom ułatwień dostępu w metodzie dostępu musi być bardziej restrykcyjny niż poziom ułatwień dostępu w samej właściwości lub indeksatorze.

Modyfikatory dostępu w zastępowaniu metod dostępu

Po zastąpieniu właściwości lub indeksatora przesłonięć metody dostępu muszą być dostępne dla zastępowania kodu. Ponadto dostępność zarówno właściwości/indeksatora, jak i jej akcesoriów musi być zgodna z odpowiednią właściwością/indeksatorem przesłonięć i jego metodami dostępu. Na przykład:

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; }
    }
}

Implementowanie interfejsów

Jeśli używasz metody dostępu do implementowania interfejsu, metoda dostępu może nie mieć modyfikatora dostępu. Jeśli jednak zaimplementujesz interfejs przy użyciu jednego metody dostępu, takiego jak get, drugi dostęp może mieć modyfikator dostępu, jak w poniższym przykładzie:

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 { }
    }
}

Domena ułatwień dostępu dostępu

Jeśli używasz modyfikatora dostępu w metodzie dostępu, domena ułatwień dostępu metody dostępu jest określana przez ten modyfikator.

Jeśli nie użyto modyfikatora dostępu na metodzie dostępu, domena ułatwień dostępu jest określana przez poziom ułatwień dostępu właściwości lub indeksatora.

Przykład

Poniższy przykład zawiera trzy klasy, BaseClass, DerivedClassi MainClass. Istnieją dwie właściwości w obiekcie BaseClassi NameId w obu klasach. W przykładzie pokazano, w jaki sposób właściwość może być ukryta przez właściwość IdDerivedClassId w BaseClass przypadku używania restrykcyjnego modyfikatora dostępu, takiego jak chronione lub prywatne. W związku z tym podczas przypisywania wartości do tej właściwości właściwość jest wywoływana BaseClass w zamiast tego. Zastąpienie modyfikatora dostępu przez publiczne spowoduje, że właściwość będzie dostępna.

W przykładzie pokazano również, że restrykcyjny modyfikator dostępu, taki jak private lub , na set metodzie dostępu do właściwości w programie DerivedClass uniemożliwia dostęp do metody dostępu Name w protectedklasie pochodnej. Generuje błąd podczas przypisywania do niego lub uzyskuje dostęp do właściwości klasy bazowej o tej samej nazwie, jeśli jest dostępny.

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
*/

Komentarze

Zwróć uwagę, że jeśli zastąpisz deklarację new private string Id przez new public string Id, otrzymasz dane wyjściowe:

Name and ID in the base class: Name-BaseClass, ID-BaseClass Name and ID in the derived class: John, John123

Zobacz też