C # 的部分类设计不好吗?

我想知道为什么“部分类”的概念甚至存在于 C #/VB.NET 中。我正在开发一个应用程序,我们正在阅读一本(实际上非常好的)与我们正在实现的开发平台相关的书。在这本书中,作者提供了一个大型的平台 API 代码库/包装器,并解释了他是如何在教授平台开发的不同主题时开发这个平台的。

无论如何,长话短说——他使用部分类,到处都是,作为在 c # (IMO)中伪造多重继承的一种方法。我不明白他为什么不把课程分成多个部分,然后使用作文。他将有3个“部分类”文件来构成他的基类,每个 w/3-500行代码... 并且在他的 API 中多次这样做。

你觉得这合理吗?如果是我,我会遵循 S.R.P。 ,创建多个类来处理不同的需求行为,然后创建一个基类,将这些类的实例作为成员(例如组合)。为什么 MS 甚至将部分类放入框架中?他们移除了在 C # 的每个作用域级别展开/折叠所有代码的能力(这在 C + + 中是允许的) ,因为它显然只是允许坏习惯-部分类,IMO,是一回事。我想我的问题是: 你能解释一下什么时候才有合理的理由使用分部类吗?

编辑: 我知道对于 Web/WinForms 来说没有其他选择。但除此之外呢?为什么 MS 不把一些不同的关键字粘在一起生成代码的类?或者真的有一个合法的设计方案值得这样做?

我不是说这是一个咆哮/战争的线索。我真的想在这里学点东西。什么时候应该在代码设计中使用分部类?简单的问题,不需要关闭

谢谢

25639 次浏览

你能解释一下什么时候才有合理的理由使用分部类吗?

最合理和有用的原因之一是鼓励将自动生成的代码和您自己的自定义扩展分离开来。例如,从某种设计器自动生成表单代码是很常见的,但您通常希望向其添加自己的特定行为。这样,如果重新生成自动代码部分,就不会触及具有特定扩展的部分。

也就是说,一件好东西很可能有太多的好处。一些建议:

  • 不要为了成为 partial而让你的课程成为 partial

  • 除了彼此之外,不要把部分类放在任何地方。如果你不得不跳到一个完全不相关的项目部分来查看类的另一半,你可能做错了。

  • 不要使用 partial作为掩盖类大小的技术。如果你用 partial分解你的课程,因为它们太大了,你应该重新访问 单一责任原则

  • 如果对于同一个类有三个或更多的 partial片段,那么几乎可以肯定您滥用了部分。二是典型的合理性上限,通常用于从手写代码中分割自动生成的代码。

无论如何,长话短说——他使用部分类,到处都是,作为在 c # (IMO)中伪造多重继承的一种方法。他为什么不把课程分成多个部分,然后用作文,我实在想不通。他将有3个“部分类”文件来构成他的基类,每个 w/3-500行代码... 并且在他的 API 中多次这样做。

是的,这绝对是对 partial的滥用!

你能解释一下什么时候才有合理的理由使用分部类吗?

VisualStudio 的最新版本使用分部类将自动生成的设计器代码与您自己的代码分开。

一个 ASP.NET 的例子:

  • Page.aspx
  • Page.aspx.cs <-你的代码
  • Cs <-包含自动生成代码的部分类。

一个 WinForms 的例子:

  • 表格1.resx
  • Form1.cs <-您的代码
  • Form1.designer.cs <-包含自动生成代码的分部类

我使用分部类有两个原因。

  1. 分隔代码的自动生成部分(如 WinForms 设计器代码或 T4输出)。
  2. 允许嵌套类型自己的文件,同时仍然实现设计所需的封装。

更新
我可以看到有些人不相信我的第二点,所以让我给出一个例子: 框架中的 ListViewItemCollection。它正确地嵌套在 ListView之下,因为它只供 ListView使用,但是为了更容易维护,我将使用分部类给它自己的文件。我不认为这是糟糕的设计或者是对 partial关键字的误用。

要了解更多的讨论,请查看这个重复的问题: C # 中的部分类

部分类的另一个合法用途是帮助减少 WCF 中的“单一 Web 服务”混乱。您希望将其分解为功能的逻辑组,但不希望创建大量单独的服务实例/端点(可能是因为它们共享状态、资源等)。

解决办法?让服务实现多个接口,并在其自己的分部类中实现每个接口。然后将配置中的不同端点映射到相同的物理实现。它使得项目更易于维护,但是您仍然只有一个物理端点。

在某些情况下,由于 SRP 的原因,我会指出这种类型的方法是一种糟糕的实践,但是当您使用 WCF 服务或 Web 服务时,通常情况下,它并不是那么简单。您必须平衡内部设计需求和外部消耗需求。

类中存在部分类。Net 框架 独自一人,让 VisualStudio 设计器(例如,Asp。Net 设计器和 Windows 窗体设计器)来生成代码/混乱您的类,同时将生成的代码保存在一个单独的文件中。

(见 .NET 部分类与继承)

如果您做类似的事情(生成需要与用户编写的代码共存的代码) ,那么您可能还会发现部分类是有用的,但是 我认为微软从来没有打算将部分类作为一种语言概念来对 VisualStudio 团队以外的任何人有用。

使用部分类并不是糟糕的设计——只是你可能找不到它们的用途。

我完全同意 约翰的的回答,但我会更进一步。

  • 不要让你的课成为部分课程。

我认为“优秀设计”的部分类的唯一用法是使用自动生成的代码。任何其他用法几乎都是不必要地拆分类。(实际上,我可以看到,嵌套类上的 杰夫的第二点可能是一个有效的用法)

就我个人而言,我认为你正在读的这本书听起来像是糟糕的设计,但是请考虑到他可能只是使用了部分类,这样他就可以一次只演示部分代码,而不是一次性展示整个类。

我使用部分类“物理地”将静态数据访问方法与活动记录体系结构中的业务类属性和方法分开。例如,我们将 Company 和 CompanyData 分部类并排放置。优点是一个文件是 POCO,另一个文件只包含数据访问方法。这是在遗留应用程序中删除对存储库类的数据访问的垫脚石。我认为这是一个合法的使用,它肯定使重构过程更理智。

一个不太常见的用法可能是将一个巨大的类拆分为单独的物理文件,从源代码控制的角度来看,这样做更方便。我刚刚加入了一个项目,该项目包含一些非常庞大的 Web 服务类,这些类可以运行数千行代码,并且使用与几个不同业务功能相关的方法。

由于不同的团队在同一个文件中同时进行不相关的更改,从不同的特性分支合并是一个噩梦。我不能在不做出一些重大改变的情况下将 Web 服务分割开来,但是将类分割成部分类可以精确地保留行为,并消除一大堆合并问题。

我当然不鼓励以上作为一个设计选择,但它是一个不错的快速胜利为我们,并表明部分不是邪恶的 所有的时间..。

部分类的另一个好用途是在实现 抽象工厂模式时。使根工厂对象部分化,然后将实际的工厂方法放在与工厂实例化的类相同的文件中。

编辑: 部分类对于与配置文件交互的类也能很好地工作。将包含配置参数的代码放在实际使用配置参数的代码附近。

我在 VB.Net 中使用了两次分部类,这两次都是为了在极少数情况下需要后期绑定。只需创建一个分部类并在顶部关闭 OptionStrictOff 即可。

为了补充前面提到的将生成的代码与自定义代码分离的答案,我发现部分类对于扩展强类型数据集非常有用。

关于这个话题有很多讨论,很多人说1)使用部分类是糟糕的设计,2)它用于自动生成代码,3)它不应该取代继承。

但是,我遇到了这样一种情况: 部分类看起来非常方便: 我正在构建一系列应用程序,它们最终将集成到一个套件中。它们都有一个提供一些功能的主窗体和几个共享组件(例如,一个显示报表的窗体)。虽然我定义了一个基类并从中继承,但是当需要将所有应用程序合并到产品的“企业”版本时,这意味着需要进行大量的重复工作。

因此,分部类非常有用,因为我可以很简单地将各种分部类包含到组合版本中,同时仍然允许我构建产品的单独版本。如果我试图通过继承来完成这个任务,我会让每个组件调用它自己版本的公共组件(例如,InvoiceReportViewer,PurchasingReportsViewer,等等) ,而不是简单地调用 ReportsViewer,并且知道 Visual Studio 已经为我集成了所有的比特。

只是在谷歌部分课程的好处时偶然发现了这个线程。 我正在将 JavaEE 应用程序转换为基于.NET 的 Silverlight 应用程序。 我在视图层中发现了以下代码:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.225
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------


...


public partial class Wwcusts04d : System.Windows.Controls.Page {

现在,如果部分页面本身是自动生成的,那么维护它有什么用呢? 此外,内部的代码只是将各种控件链接到它们的名称。我不承认我了解银光,但是这东西不是更适合在 Xaml 吗?

在过去,我曾经以许多不同的方式使用过部分类。随着我对编程的了解越来越多,特别是“优先组合优先于继承”的概念,我可以很容易地看到垂直继承和过度使用部分类的需求正在减少。

除了自动生成的代码之外,我想不出还有什么方法可以很好地使用部分类。即使您使用 EF,并且需要不同的元数据,他们甚至不建议使用部分元数据。事实上,如果您试图复制另一个部分中的任何属性(只是为了添加元数据) ,您将得到一个编译器错误。

我们对重构和 SOC (关注点分离)了解得越多,我们的类就变得越小、越集中。它们在默认情况下是可重用的,随着时间的推移,这使得它们防弹和易于测试。只要对庞大的程序说不。亨利 · 福特在1900年代早期学会了这个概念,100年后程序员开始学习。

能用的时候就用作文..。

还有一件事要考虑,分部类强制您创建包含相同类名的不同文件名。例如,你有一个 FactoryClass,你正在创建它的部分版本,比如, factory.designer.cs ,Factory.data.cs 和所有这些文件都有一个名为 FactoryClass 的类。

如果你导航到 这个问题; 有一个 最佳实践定义为:

但是,最佳实践是为每个文件定义一个类,并为文件提供与正在定义的类(或 struct 等)相同的名称。