如何访问嵌套类的私有成员?

gre*_*man 15 c# design-patterns

背景:我已经使用嵌套类N封装了(父)类E,在E中有几个N实例.在封闭的(父)类中,我正在进行一些计算,我正在为嵌套类的每个实例设置值.像这样的东西:

n1.field1 = ...;
n1.field2 = ...;
n1.field3 = ...;
n2.field1 = ...;
...
Run Code Online (Sandbox Code Playgroud)

它是一个大的eval方法(在父类中).我的意图是 - 因为所有计算都在父类中(它们不能按照嵌套实例进行,因为它会使代码更复杂) - 使setter仅对父类和getter公共可用.

现在有一个问题:

  • 当我将setter设为私有时,父类无法访问它们
  • 当我公开它们时,每个人都可以改变价值观
  • 和C#没有朋友的概念
  • 我无法在构造函数中传递值,因为使用了惰性求值机制(因此必须在引用它们时创建实例 - 我创建所有对象并按需触发计算)

我被困 - 怎么做(限制访问父类,不多也不少)?


我怀疑我会先回答问题 - "但是为什么你不按每个字段拆分评估" - 所以我通过例子回答这个问题:你如何计算集合的最小值和最大值?快点?答案是 - 一次通过.这就是为什么我有一个eval函数可以进行计算并一次设置所有字段.

Tho*_*que 48

您可以在E私有接口内声明IN,显式实现N.此接口N仅通过E以下方式公开可访问的成员:

public class E
{
    public void Foo()
    {
      IN n = new N();
      n.Field1 = 42;
    }

    public class N : IN
    {
        private int _field1;

        int IN.Field1
        {
            get { return _field1; }
            set { _field1 = value; }
        }
    }

    private interface IN
    {
        int Field1 { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢托马斯,这比接受的答案要好得多! (6认同)
  • 我认为你误解了我的答案......`IN`界面从来没有打算公开.它只是嵌套类仅将属性公开给包含类的一种方法.如果需要,您还可以在`N`中创建公共getter (2认同)
  • 好吧,是的,重点是......那样,只有父类可以设置嵌套类私有字段 (2认同)

Cod*_*uth 7

如果您可以将父类和子类放在另一个程序集中,则可以使用internalsetter.这通常是如何在野外处理的.

编辑:

Thomas Levesque的回答给了我一个想法:

class Program
{
    static void Main(string[] args)
    {
        E myE = new E();

        Console.WriteLine("E.N1.Field1 = " + myE.N1.Field1);
        Console.WriteLine("E.N2.Field1 = " + myE.N2.Field1);
    }

    public interface IN
    {
        int Field1 { get; }
    }

    public class E
    {
        private N _n1 = new N();
        private N _n2 = new N();

        public E()
        {
            _n1.Field1 = 42;
            _n2.Field1 = 23;
        }

        public IN N1
        {
            get { return _n1; }
        }

        public IN N2
        {
            get { return _n2; }
        }

        private class N : IN
        {
            private int _field1;

            public int Field1
            {
                get { return _field1; }
                set { _field1 = value; }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

根据您需要如何公开子类N,这可能会起作用.

  • 谢谢,但它是一个文件,没有那么大,所以设置这个单独的程序集似乎有点过分了。 (2认同)

naw*_*fal 7

如果您的(嵌套)类是私有的,另一种方法是让您希望成为私人公开的成员.如果私有类的字段是公共的,它只会暴露给封闭的类.

public class E
{
    public void Foo()
    {
      IN n = new N();
      n.field1 = 42;
    }

    class N : IN
    {
        public int _field1;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在N只有可见E,所以n._field1公开只对E你很重要,而且你很安全..