Почему и как C # разрешает доступ к закрытым переменным вне самого класса, если он находится внутри того же самого содержащего класса? - PullRequest
20 голосов
/ 21 апреля 2011

Я не знаю, достаточно ли описательный вопрос, но почему и как такое поведение существует:

public class Layer
{
    public string Name { get; set; }

    private IEnumerable<Layer> children;
    public IEnumerable<Layer> Children
    {
        get { return this.children.Where ( c => c.Name != null ).Select ( c => c ); }
        set { this.children = value; }
    }

    public Layer ( )
    {
        this.children = new List<Layer> ( ); // Fine

        Layer layer = new Layer ( );
        layer.children = new List<Layer> ( ); // Isn't .children private from the outside?
    }
}

Я могу получить доступ к layer.Children где угодно, это нормально, но как я могу получить доступ к layer.children, поскольку это личное?

Layer layer = new Layer ( );
layer.children = new List<Layer> ( );

работает, только если код находится внутри класса Layer.Существует ли специальный код для обработки доступа к закрытым переменным по-разному, если он выполняется внутри содержащего класса, даже если доступ осуществляется извне?

Я знаю причину использования:

this.children = ...

изнутрисодержащий класс, но создающий новые экземпляры и модифицирующий их извне, даже если они все еще находятся внутри содержащего класса, не кажется хорошей практикой.

В чем причина такого разрешения?

Ответы [ 3 ]

25 голосов
/ 21 апреля 2011

См. Раздел 3.5.1 спецификации языка C #. Соответствующий текст таков:

Частный, который выбирается в том числе частный модификатор в декларация участника. Интуитивно понятный значение частного означает «доступ ограничен к содержащему типу ».

Обратите внимание, что модификатор относится к типу , а не к экземпляру .

А затем далее в разделе 3.5.2 дополнительно разъясняются некоторые правила:

В интуитивно понятном смысле, когда тип или доступ к члену М, следующий шаги оцениваются, чтобы гарантировать, что доступ разрешен:

  • Во-первых, если M объявлено внутри типа (в отличие от единицы компиляции или пространство имен), ошибка времени компиляции происходит, если этот тип недоступен.
  • Тогда, если M является публичной, доступ разрешен.
  • В противном случае, если M защищен внутри, доступ разрешен, если это происходит в рамках программы, в которой М объявлен, или если это происходит в пределах класс, производный от класса в который М объявлен и имеет место через производный тип класса (§3.5.3).
  • В противном случае, если M защищен, доступ разрешается, если это происходит в классе, в котором М объявлено, или если это происходит в течение класс, полученный из класса, в котором М объявлен и проходит через тип производного класса (§3.5.3).
  • В противном случае, если M является внутренним, доступ разрешается, если это происходит в программе, в которой М объявлено.
  • В противном случае, если M является частным, доступ разрешается, если это происходит в типе, в котором М объявлен.
  • В противном случае тип или член недоступны, и ошибка времени компиляции происходит.
7 голосов
/ 21 апреля 2011

Это обычный дизайн.Предполагается, что тот, кто написал класс, знает, как правильно с ним работать, и понимает, что означает прямой доступ к закрытым членам.Так что доступ к закрытым членам других экземпляров того же класса часто работает.Если вы знакомы с конструкцией C ++ friend, то похоже, что все экземпляры одного класса дружат друг с другом (хотя C # официально не имеет понятия friend).

Это работает в C # и Javaэто те два языка, которые я знаю на макушке.Могу поспорить, многие другие языки также позволяют это (кто-то хочет присоединиться?)

3 голосов
/ 21 апреля 2011

Помните, модификатор частного доступа говорит Private members are accessible only within the body of the class or the struct in which they are declared.Это описание сбивает с толку, но оно ясно говорит, что ограничение на уровне класса и NOT OBJECT LEVEL.В этом случае слой все еще находится внутри класса.

Это обсуждалось здесь ранее. можем ли мы получить доступ к закрытой переменной, используя объект

...