当C#在同一个包含的类中时,为什么以及如何允许访问类本身之外的私有变量?

Joa*_*nge 20 .net c# compiler-construction class private-members

我不知道问题是否足够描述,但为什么以及如何存在这种行为?:

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?
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以访问layer.Children任何地方,这很好,但我怎么能访问,layer.children因为它是私人的?

Layer layer = new Layer ( );
layer.children = new List<Layer> ( );
Run Code Online (Sandbox Code Playgroud)

仅当代码在Layer类中时才有效.是否有特殊代码来处理访问私有变量,如果它是在包含类内完成的,即使访问来自外部?

我知道使用的原因:

this.children = ...
Run Code Online (Sandbox Code Playgroud)

在包含类的内部,但是创建新实例并从外部修改它们,即使它们仍在包含类中,也不是一个好习惯.

允许这个的原因是什么?

Ant*_*ram 25

请参阅C#语言规范的第3.5.1节.相关文字是这样的:

私有,通过在成员声明中包含私有修饰符来选择.private的直观含义是"访问仅限于包含类型".

请注意,修饰符与类型相关,而不是实例.

然后在3.5.2节中进一步解释了一些规则:

直观地说,当访问类型或成员M时,将评估以下步骤以确保允许访问:

  • 首先,如果在一个类型(而不是编译单元或命名空间)中声明了M,则如果该类型不可访问则会发生编译时错误.
  • 然后,如果M是公共的,则允许访问.
  • 否则,如果M在内部受保护,则允许访问,如果它发生在声明M的程序中,或者它发生在从声明M的类派生的类中,并通过派生类类型发生(§ 3.5.3).
  • 否则,如果M受保护,则允许访问,如果它发生在声明M的类中,或者它发生在从声明M的类派生的类中,并通过派生类类型发生(§3.5) 0.3).
  • 否则,如果M是内部的,则允许访问,如果它发生在声明M的程序中.
  • 否则,如果M是私有的,则允许访问,如果它发生在声明M的类型中.
  • 否则,类型或成员不可访问,并发生编译时错误.


Mat*_*eer 7

这是一种常见的设计.假设编写该类的人知道如何正确使用它并理解直接访问私有成员意味着什么.因此,访问同一类的其他实例的私有成员通常有效.如果你熟悉C++的friend结构,那么它就像同一个类的实例都是朋友互相(虽然C#没有friend概念正式).

这适用于C#和Java,这些是我所知道的两种语言.我敢打赌许多其他语言也允许这样(任何人都想要插入?)