【问题标题】:What's the best way of accessing field in the enclosing class from the nested class?从嵌套类访问封闭类中的字段的最佳方法是什么?
【发布时间】:2010-09-16 03:42:20
【问题描述】:

假设我在表单中有一个下拉菜单,并且我在这个类中还有另一个嵌套类。 现在从嵌套类访问此下拉列表的最佳方法是什么?

【问题讨论】:

  • 请详细说明。例子会很好。
  • 学习者,我已在您的问题中添加了nestedclasses 标签,因为有一个带有该标签的“我什么时候应该使用嵌套类”问题,并且将这两个更紧密地分组比简单地使用 C# 标签更有意义!
  • 能够做到这一点(使用标准语法)的前景非常有趣……有点像行为上的闭包。毫无疑问,如果存在的话,这样的特性会被滥用,直到它成为反模式 =(

标签: c# .net inner-classes


【解决方案1】:

上面有一个很好的答案,但我喜欢写什么。

c# 嵌套类默认是私有的

私有到包含类如果你想使用它必须是公共的

【讨论】:

    【解决方案2】:

    与 Java 不同,嵌套类不是特殊的“内部类”,因此您需要传递引用。 Raymond Chen 在这里有一个描述差异的例子:C# nested classes are like C++ nested classes, not Java inner classes

    这是一个示例,其中嵌套类的构造函数被传递给外部类的实例以供以后参考。

    // C#
    class OuterClass 
    {
        string s;
        // ...
        class InnerClass 
        {
           OuterClass o_;
           public InnerClass(OuterClass o) { o_ = o; }
           public string GetOuterString() { return o_.s; }
        }
        void SomeFunction() {
            InnerClass i = new InnerClass(this);
            i.GetOuterString();
        }
    
    }
    

    注意,InnerClass 可以访问 OuterClass 的“s”,我没有修改 Raymond 的代码(正如我上面链接的那样),所以请记住“string s;”是private,因为没有其他指定了访问权限。

    【讨论】:

      【解决方案3】:

      嵌套类型不像 Java 中的内部类 - 没有包含类型的固有实例。 (它们更像是 Java 中的静态嵌套类。)它们实际上是独立的类,有两个区别:

      • 如果包含类型是泛型,则嵌套类型由包含类型有效地参数化,例如Outer<int>.NestedOuter<string>.Nested 不同。
      • 嵌套类型可以访问包含类型中的私有成员。

      【讨论】:

      • (大约 7 年后...)您知道为什么外部类不能访问嵌套类的私有或受保护成员,就像嵌套类可以访问外部类成员一样?有时这会很有用,我想知道我的设计是否存在缺陷。
      • @GDS:我不知道为什么做出这个设计决定,但它通常对我来说是有意义的。如果您将嵌套类设为私有,那么将成员设为内部或公开都很好。
      • 没错,但在某些情况下,您是否希望内部甚至公共嵌套类但其私有和受保护成员对外部类可见?那里有潜在的缺陷吗?
      • @GDS:我只能说我自己没有遇到过这些情况。我无法推测设计的确切原因。
      【解决方案4】:

      将主类作为构造函数参数发送到嵌套(内部)类。

      【讨论】:

        【解决方案5】:

        在某些情况下有用的另一种方法是从外部类派生嵌套类。像这样:

        class Outer()
        {
            protected int outerVar;
            class Nested() : Outer
            {
                //can access outerVar here, without the need for a 
                // reference variable (or the associated dot notation).
            }
        }
        

        我已经使用过这种技术,尤其是在Structured Unit Tests 的上下文中。 (这可能不适用于 OP 的特定问题,但通常对嵌套类很有帮助,例如这个“重复”问题:“Can i access outer class objects in inner class”)

        【讨论】:

        • 现在这是一个有趣的想法,与其他答案有点不同。但是,我很确定你不能实例化 existing 对象实例的子类,所以如果你已经有一个 Outer 实例并且想要一个与你现有的 @ 对应的 Nested 实例987654326@ 实例,我认为这行不通。
        • 这里的问题是创建一个新的'Nested实例会调用外部Class的'ctor,很可能导致堆栈溢出。
        【解决方案6】:

        静态成员

        由于目前还没有人提到它:根据你的情况,如果成员变量也可以是静态的,你可以通过以下方式访问它。

        class OuterClass
        {
            private static int memberVar;
        
            class NestedClass 
            {
                void SomeFunction() { OuterClass.memberVar = 42; }
            }
        }
        

        旁注:我有意(且冗余地)将memberVar 标记为private,以说明嵌套类访问其外部类的私有成员的给定能力。

        注意/请考虑

        某些情况下,这可能是获得访问权限的最简单方法/解决方法,但是...

        • 静态也意味着,该变量将在所有实例对象之间共享,存在所有缺点/后果(线程安全等)

        • 静态也意味着,如果您有多个父类的实例并且变量应该为每个实例保存一个单独的值,这显然不起作用

        所以在大多数情况下,您可能想采用不同的方法......

        传递参考

        正如大多数人所建议的(并且因为它也是最正确的答案),这里是一个传递对外部类实例的引用的示例。

        class OuterClass
        {
            private int memberVar;
            private NestedClass n;
        
            OuterClass()   { n = new NestedClass(this); }
        
        
            class NestedClass
            {
                private OuterClass parent;
        
                NestedClass(OuterClass p) { parent = p; }
                SomeFunction() { parent.memberVar = 42; }
            }
        }
        

        【讨论】:

          【解决方案7】:

          如果我错了,请纠正我,您正试图从内部类处理外部控件,因此您遇到了这个问题。更好的方法是以事件驱动的方式处理事务。使用观察者模式,在外部控件上注册一个侦听器(您的嵌套/内部类将是侦听器)。让生活更简单。恐怕这不是你期待的答案!

          【讨论】:

            【解决方案8】:

            您可以将封闭类作为参数传递给嵌套类构造函数,如下所示:

            private NestedClass _nestedClass;
            public ParentClass() 
            {
               _nestedClass = new NestedClass(this);
            }
            

            通常不建议使用嵌套类,它应该是私有的和/或内部的。但在我看来,它们有时很有用。

            【讨论】:

              【解决方案9】:

              与 Java 不同,在 C# 中没有对封闭类实例的隐式引用。

              您需要将这样的引用传递给嵌套类。执行此操作的典型方法是通过嵌套类的构造函数。

              public partial class Form1 : Form
              {
                  private Nested m_Nested;
              
                  public Form1()
                  {
                      InitializeComponent();
              
                      m_Nested = new Nested(this);
                      m_Nested.Test();
                  }
              
                  private class Nested
                  {
                      private Form1 m_Parent;
              
                      protected Form1 Parent
                      {
                          get
                          {
                              return m_Parent;
                          }
                      }
              
                      public Nested(Form1 parent)
                      {
                          m_Parent = parent;
                      }
              
                      public void Test()
                      {
                          this.Parent.textBox1.Text = "Testing access to parent Form's control";
                      }
                  }
              }
              

              【讨论】:

              • 这似乎还有一个优点,与 Java 不同,内部类的实例可以访问外部类的 any 实例的私有成员,而不仅仅是外部类-创建内部类实例的类实例(即Form1 form = new Form1(); new Nested(form);是合法的。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-11-13
              • 2021-11-06
              • 2020-04-10
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多