Ограничение доступности методов доступа (Руководство по программированию на C#)

Выражения get и set свойства или индексатора называются методами доступа. По умолчанию они имеют такие же уровни видимости или доступа, что и свойство или индексатор, которым они принадлежат. Дополнительные сведения см. в разделе Уровни доступа. Однако иногда полезно ограничить доступ к одному из этих методов доступа. Как правило, вы ограничиваете специальные возможности set метода доступа, сохраняя общедоступный доступ к методу get доступа. Например:

private string _name = "Hello";

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

В этом примере свойство Name определяет методы доступа get и set. Метод доступа get получает уровень доступа самого свойства (в этом случае public), а к методу set явным образом применяется модификатор доступа protected.

Примечание.

В примерах этой статьи не используются автоматически реализованные свойства. Автоматически реализованные свойства предоставляют краткий синтаксис для объявления свойств, если настраиваемое поле резервного копирования не требуется.

Ограничения модификаторов доступа для методов доступа

При использовании модификаторов доступа для свойств или индексаторов необходимо соблюдать следующие ограничения:

  • Модификатор доступа нельзя использовать в интерфейсе или явной реализации элемента интерфейса .
  • Модификаторы доступа можно использовать только в том случае, если для свойства или индексатора определены одновременно методы доступа set и get. В этом случае модификатор может применяться только к одному из двух методов доступа.
  • Если свойству или индексатору назначен модификатор override, модификатор доступа должен соответствовать методу доступа для переопределенного метода доступа, если такой существует.
  • Уровень доступности для метода доступа должен быть более строгим по сравнению с уровнем доступа самого свойства или идентификатора.

Модификаторы доступа при переопределении методов доступа

При переопределении свойства или индексатора переопределенные методы доступа должны быть доступны коду переопределения. Кроме того, уровни доступа свойства или индексатора и их методов доступа должны совпадать с уровнями переопределенных свойства или индексатора и их методов доступа. Например:

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

Реализация интерфейсов

Методы доступа, которые используются для реализации интерфейса, не могут иметь модификаторы доступа. Тем не менее при реализации интерфейса с использованием одного метода доступа (например, get) другой метод доступа может иметь модификатор доступа, как показано в следующем примере:

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

Домен доступности для метода доступа

При использовании модификатора доступа для метода доступа этот модификатор определяет домен доступности для такого метода.

Если в методе доступа не использовался модификатор доступа, домен специальных возможностей метода доступа определяется уровнем доступности свойства или индексатора.

Пример

В следующем примере определяются три класса: BaseClass, DerivedClass и MainClass. В классе BaseClass для обоих классов определены свойства Name и Id. В этом примере демонстрируется, как свойство Id класса DerivedClass может быть скрыто свойством Id класса BaseClass при использовании ограничивающего модификатора доступа, такого как protected или private. Таким образом, при присвоении значений этому свойству вместо него вызывается свойство класса BaseClass. Чтобы сделать это свойство доступным, необходимо заменить модификатор доступа на public.

В этом примере также показано, что модификатор ограниченного Name доступа, например private или protected, при set доступе к свойству запрещается DerivedClass доступ к методу доступа в производном классе. Он создает ошибку при назначении ему или получает доступ к свойству базового класса того же имени, если он доступен.

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

Комментарии

Обратите внимание, что если заменить объявление new private string Id на new public string Id, будут получены следующие выходные данные:

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

См. также