我想我可以使用私有嵌套类来创建属于大型类的小辅助类,但通常我会需要另一个类的辅助类,所以我只需额外付出一点努力来(1)使嵌套类成为非嵌套类或(2)将其公开,然后在其前缀上使用外部类,这似乎是额外的工作,并没有为首先拥有嵌套类增加任何附加价值。因此,总体而言,我真的看不出嵌套类的用例,除了可能将类保持更有组织性的分组,但这也违背了我喜欢的每个文件一个类的清晰度。 您如何使用嵌套类使您的代码更易管理、可读性更高、效率更高?
abstract public class BankAccount
{
private BankAccount() { }
// Now no one else can extend BankAccount because a derived class
// must be able to call a constructor, but all the constructors are
// private!
private sealed class ChequingAccount : BankAccount { ... }
public static BankAccount MakeChequingAccount() { return new ChequingAccount(); }
private sealed class SavingsAccount : BankAccount { ... }
等等,嵌套类与工厂模式结合得很好。这里的BankAccount是各种银行账户类型的工厂,所有这些类型都可以使用BankAccount的私有实现细节。但是第三方无法创建自己的类型EvilBankAccount来扩展BankAccount。
public class Outer
{
private class Inner : IEnumerable<Foo>
{
/* Presumably this class contains some functionality which Outer needs
* to access, but which shouldn't be visible to callers
*/
}
public IEnumerable<Foo> GetFoos()
{
return new Inner();
}
}
私有的辅助类是一个很好的例子。
例如,用于后台线程的状态对象。没有强制要求将这些类型公开。将它们定义为私有嵌套类型似乎是一种非常干净的处理方式。
当两个绑定值(如哈希表中)在内部不够用,但在外部足够时,我会使用它们。然后创建一个具有需要存储的属性的嵌套类,并通过方法仅公开其中几个。
我认为这很有意义,因为如果没有其他人要使用它,为什么要创建外部类呢?这就没有意义。
至于每个文件一个类,您可以使用partial
关键字创建部分类,这是我通常做的。
最近我遇到的一个引人注目的例子是许多数据结构中的Node
类。例如,一个Quadtree
需要知道它在节点中存储数据的方式,但你的代码中的其他部分不应该关心这些细节。
我认为其他人已经很好地涵盖了公共和私有嵌套类的用例。
我没有看到的一点是回答你对每个文件一个类的担忧。您可以通过将外部类设为partial,并将内部类定义移动到单独的文件中来解决此问题。
OuterClass.cs:
namespace MyNameSpace
{
public partial class OuterClass
{
// main class members here
// can use inner class
}
}
OuterClass.Inner.cs:
namespace MyNameSpace
{
public partial class OuterClass
{
private class Inner
{
// inner class members here
}
}
}
这种技术常用于某些场景,例如一个类从其属性或方法返回一个接口或基类类型,但具体类型是一个私有嵌套类。请考虑以下示例。
public class MyCollection : IEnumerable
{
public IEnumerator GetEnumerator()
{
return new MyEnumerator();
}
private class MyEnumerator
{
}
}
在某些情况下,我通常会将SRP(单一职责原则)相结合。
"好吧,如果SRP是你的目标,为什么不将它们拆分成不同的类呢?" 你可以在80%的时间里这样做,但是如果创建的类对外部世界没有用处怎么办?你不希望只有你自己使用的类会使你的程序集API变得混乱。
"那么internal
就是为此而设的了吗?" 当然,对于这80%的情况是这样。但是对于必须访问或修改公共类状态的内部类呢?例如,为了满足你的SRP streak而将一个类分解为一个或多个内部类的情况?你需要将所有方法和属性标记为internal
,以供这些internal
类使用。
"这有什么问题吗?" 对于这80%的情况没有什么问题。当然,现在你的类的内部接口被那些你之前创建的类才能使用的方法/属性所占据。现在你还需要担心团队中的其他人编写的内部代码是否会通过使用你未预期的方式来使用这些方法而破坏你的状态。
内部类可以修改其定义类型的任何实例的状态。因此,不需要向类型定义中添加成员,你的内部类就可以根据需要对它们进行操作。在100个案例中的14个案例中,这将是保持类型简洁、代码可靠/可维护和责任单一的最佳选择。