在C#中另一个类中声明的类

我正在处理一些遗留代码,并遇到了一些我不确定的事情。 我们有一个在另一个class x声明的class xClass y只在class x使用,但我的问题是为什么你不创build一个单独的类文件,并把class y放在那里,而不是在class x中声明它? 这不是违反了OOP吗?还是只是一个风格问题,因为它只被用在这个类的内部。 我正在重构这些代码,我的第一个反应是把class y到它自己的文件中。

 namespace Library { public class x { // methods, properties, local members of class x class y { // methods, properties, local members of class y } } } 

您创build一个内部类,因为它只能在类x的范围内使用,并且在逻辑上适合类x的因式分解/体系结构。

y类可能也会涉及到公众不知道的类x的实现细节。

这具有权限影响。 一个顶级的“class y”将是“internal” – 然而,这里的“y”是“x”的私有的。 这种方法对实现细节(例如caching行等)很有帮助。 同样, y有权访问x所有私有状态。

对generics也有影响; x<T>.yx<T>.ygenerics,从外部类inheritance。 你可以在这里看到这个, Bar充分使用了T – 并且注意Bar任何静态字段都是作用域的。

 class Foo<T> { void Test(T value) { Bar bar = new Bar(); bar.Value = value; } class Bar { public T Value { get; set; } } } 

通常人们错误地认为他们需要将Bar定义为Bar<T> – 现在(有效)是双重generics的,即Foo<TOld, T> – 其中TOldFoo<T>的(现在不可用的) T . 所以不要这样做! 或者,如果你想要它是双重通用的,select不同的名称。 幸运的是,编译器警告你这个…

这个代码对于你给出的确切原因是很好的 – “类y只能在类x中使用”。 这些是嵌套types ,使用它们的指导原则之一是嵌套types应该与它们的声明types紧密耦合,并且不能用作通用types。 这样的嵌套类是其他类无法访问,但仍然允许您遵循面向对象的原则。

我刚刚通过我更新的代码(和我最初写),并删除所有嵌套的类。 不幸的是,我最初在定义的类之外使用了嵌套类。移动嵌套类对我来说有很大的不同,因为我原本devise不好。

如果Y只在X中使用,并且永远不会在X之外使用,我会说保留在那里

我认为没关系,只要包含的类只用作实用程序。 我使用这种结构来为私有方法定义复杂的返回types。

让我给你一个使用嵌套类的例子,可以澄清何时这种架构是适当的。 我最近需要通过从数据表中提取选定的列来生成一个HTML表格,并“旋转”它们以使行成为列,反之亦然。 在我的情况下,有两个基本的操作:旋转数据和生成一些相当复杂的输出(我不只是显示数据:每个数据列/表格行都受到提取标题,生成图像标签,设置链接,等等,因此使用SQL Pivot也不是很正确)。

在最初尝试创build一个类来完成整个事情之后,我意识到大部分数据/方法分为三个不同的分区:标题处理,行处理和旋转。 因此,我决定更好的方法是将“标题”和“行”的逻辑封装在单独的嵌套类中。 这使我能够将每行所保存的数据分开,并且非常干净地编写数据透视操作(为数据表中的每一列调用一个单独的行对象)。 在pivot操作结束时,我通过调用header对象来生成输出,然后依次将每个row对象生成输出回到主类。

单独的类是不合适的,因为A)嵌套类确实需要来自主类的一些数据,并且B)处理是非常具体的,在其他地方是没有用的。 仅仅编程一个大类就是因为“列”和“行”等术语的混淆而变得混乱,这取决于您是在讨论数据还是HTML输出。 另外,这是一个不寻常的工作,因为我在业务类中生成HTML,所以我想从UI生成中分离纯业务逻辑。 最后,嵌套类提供了封装和数据共享的完美平衡。

您仍然可以将您的类y重构为另一个文件,但是使用一个parial类。 这样做的好处是每个文件仍然有一个类,并且没有在x类以外移动声明的重构麻烦。

例如你可以有一个代码文件:xycs,看起来像

 partial class X { class Y { //implementation goes here } }