C#中的私有内部类 - 为什么不经常使用它们?

Syl*_*gue 74 c# scope inner-classes

我对C#比较陌生,每次我开始研究C#项目(我只用C#中几乎成熟的项目)我想知道为什么没有内部类?

也许我不明白他们的目标.对我来说,内部类 - 至少是私有内部类 - 看起来很像Pascal/Modula-2/Ada中的"内部程序":它们允许在较小的部分中分解主类以便于理解.

示例:这是大多数时间看到的内容:

public class ClassA
{
   public MethodA()
   {
      <some code>
      myObjectClassB.DoSomething(); // ClassB is only used by ClassA
      <some code>
   }
}

public class ClassB
{
   public DoSomething()
   {
   }
}
Run Code Online (Sandbox Code Playgroud)

由于ClassB只会被ClassA使用(至少有一段时间),我猜这个代码会更好地表达如下:

   public class ClassA
   {
      public MethodA()
      {
         <some code>
         myObjectClassB.DoSomething(); // Class B is only usable by ClassA
         <some code>
      }

      private class ClassB
      {
         public DoSomething()
         {
         }
      }
   }
Run Code Online (Sandbox Code Playgroud)

我很高兴收到你关于这个主题的消息 - 我是对的吗?

Jon*_*eet 78

嵌套类(可能最好避免使用"内部"一词作为C#中的嵌套类与Java中的内部类有些不同)确实非常有用.

一个未提及的模式是"更好的枚举"模式 - 它可以比Java更灵活:

public abstract class MyCleverEnum
{
    public static readonly MyCleverEnum First = new FirstCleverEnum();
    public static readonly MyCleverEnum Second = new SecondCleverEnum();

    // Can only be called by this type *and nested types*
    private MyCleverEnum()
    {
    }

    public abstract void SomeMethod();
    public abstract void AnotherMethod();

    private class FirstCleverEnum : MyCleverEnum
    {
        public override void SomeMethod()
        {
             // First-specific behaviour here
        }

        public override void AnotherMethod()
        {
             // First-specific behaviour here
        }
    }

    private class SecondCleverEnum : MyCleverEnum
    {
        public override void SomeMethod()
        {
             // Second-specific behaviour here
        }

        public override void AnotherMethod()
        {
             // Second-specific behaviour here
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我们可以使用一些语言支持来自动完成其中的一些操作 - 这里我没有显示很多选项,比如实际上没有为所有值使用嵌套类,或者对多个值使用相同的嵌套类,但给他们不同的构造函数参数.但基本上,嵌套类可以调用私有构造函数的事实提供了很多功能.

  • 这是真的,直到它成为公认的模式.这就像"while((line = streamReader.ReadLine())!= null)"看起来不好开始 - 在一段时间内的副作用!但是当它是惯用的时候,你就会闻到它的味道并欣赏它的简洁. (28认同)
  • 非常聪明!但我永远不会用它.软件书籍作者和他们的读者(!)通常是聪明的人.他们想到很多很棒的事情而且很酷.但软件维护者是普通人,他们没有阅读Gamma/Skeet.我的客人:越聪明,维护越少...... (10认同)
  • @Sylvain:我认为它就像 LINQ - 当您习惯它时,它“增加”了可维护性,但乍一看很奇怪。但我同意这在 C# 中还不是常见模式:( (2认同)
  • @Jon,谢谢!我想我现在明白了.`MyCleverEnum`既作为枚举成员的持有者又作为每个枚举成员的接口,因此它比其他解决方案更简洁.嵌入式类的使用可确保在类外部隐藏支持类.私有构造函数使类的行为类似于类外的静态/单例类,但类似于类内部的抽象基类. (2认同)
  • @supercat,您可以在文件顶部放置一个 using 指令“using FirstCleverEnum = MyCleverEnum.FirstCleverEnum”。这可以缓解该问题,但无法“导出”此别名。 (2认同)

mat*_*dev 30

框架设计指南有使用,我发现迄今嵌套类最好的规则.

这是一个简短的摘要列表:

  1. 当类型和嵌套类型之间的关系是需要成员可访问性语义时,请使用嵌套类型.

  2. 千万不要使用公共嵌套类型的逻辑组结构

  3. 避免使用公开暴露的嵌套类型.

  4. 千万不要如果类型可能包含类型的外部引用使用嵌套类型.

  5. 千万不要,如果他们需要通过客户机代码实例化使用嵌套类型.

  6. NOT限定嵌套类型作为接口的成员.

  • 其中一些是相当明显的(例如 4 和 5)。但您能指出推荐其他规则的原因吗? (2认同)

Wim*_*nen 12

您应该限制每个类的职责,以使每个类保持简单,可测试和可重用.私人内部阶级反对.它们有助于外部类的复杂性,它们是不可测试的,并且它们不可重复使用.

  • 我看到程序员一直使用像元组这样的数据结构而不是私有类.我肯定会争辩说私有类会导致代码更容易阅读并且更不容易出错.认为它违反了封装是不正确的.私有类违反封装没有任何意义.它包含在一个类中,应该并且确实拥有外部类的任何其他成员的所有权限. (8认同)
  • 我会选择封装作为**内部类的参数**.内部类可以访问其外部类的私有成员! (3认同)