【问题标题】:Partial Classes in C#C# 中的部分类
【发布时间】:2008-10-02 01:44:13
【问题描述】:

在 webforms/winforms 生成的代码场景之外,Partial Classes 是否有很好的用途?或者这个功能基本上是为了支持那个?

【问题讨论】:

    标签: c# partial-classes


    【解决方案1】:

    它部分支持将生成的代码与程序员代码混合的场景(WebForms、WinForms、LINQ-to-SQL 等)。

    还有更多使用它的理由。例如,如果您在大而笨重的文件中有大类,但这些类具有逻辑相关的方法组,则部分类可能是使您的文件大小更易于管理的选项。

    【讨论】:

    • "如果你在大而笨重的文件中有大类"那么你真的需要重新考虑你的设计。
    • 这取决于您对大而笨重的定义,以及您在整个地方滚动查看您想要看到的内容的容忍度以及您使用大/多个屏幕/拆分的能力窗格来查看您的工作。非常主观的分析;我不得不不同意,弗雷德里克...
    • @sweeney:如果你认为你的类足够大且笨拙到足以考虑部分,那么它们可能足够大且笨拙以考虑你的设计,无论你的“大型和笨拙”指标是什么"是。
    • @Roger:我不同意。如果您的类出于完全有效的封装原因而具有嵌套类型,它将创建大而笨重的文件,这些文件需要使用部分文件,但并不表示需要重新设计。
    • @FredrikKalseth 同意,大 class= 重构时间。我知道这是一个旧答案,但除了代码生成之外,我从未见过对部分类的良好使用,它们非常令人困惑。我会进一步说代码生成也是个坏消息,不会有什么优雅的结果。
    【解决方案2】:

    代码生成是部分类背后的驱动力。需求来自于拥有一个不断变化的代码生成类,但允许开发人员提供自定义代码作为类的一部分,这些代码不会在每次进行强制重新生成的更改时被覆盖。

    以 WinForms 或 Typed-DataSets 为例(或任何设计者)。每次您对设计器进行更改时,它都会将相应的代码序列化到文件中。假设您需要提供一些生成器不知道的附加方法。如果您将其添加到生成的文件中,您的更改将在下次生成时丢失。

    我目前正在处理的一个项目对所有 DAL、BLL 和业务实体使用代码生成。然而,生成器只能得到我们 75% 的信息。其余部分必须手动编码(例如自定义业务逻辑)。我可以假设每个 BLL 类都有一个 SelectAll 方法,因此很容易生成。但是我的客户 BLL 还需要有一个 SelectAllByLocation 方法。我不能把它放在我的生成器中,因为它不是所有 BLL 类的通用。因此,我将所有类生成为部分类,然后在一个单独的文件中定义我的自定义方法。现在,当我的结构发生变化或出于某种原因需要重新生成 BLL 时,我的自定义代码不会被清除。

    【讨论】:

      【解决方案3】:

      我使用部分类来分离我编写的自定义控件的不同子元素。此外,当与实体创建软件一起使用时,它允许像 LLBLGen 这样的产品创建类的生成版本,以及自定义的、用户编辑的版本,如果需要重新生成实体,则不会被替换。

      【讨论】:

        【解决方案4】:

        我经常使用分部类来为每个嵌套类提供自己的文件。我曾经研究过一些架构,其中大部分实现只需要一个类,因此我们将这些类嵌套在一个类中。通过使用部分类功能并将每个文件拆分到自己的文件中,使文件更易于维护是有意义的。

        我们还使用它们来对库存覆盖进行分组或隐藏一组库存属性。像这样的东西。这是一种混合库存更改的便捷方式(只需复制文件并将部分类名称更改为目标类 - 当然,只要目标类也是部分类)。

        【讨论】:

          【解决方案5】:

          部分类的另一个可能用途是利用部分方法通过条件编译使方法有选择地消失 - 这对于调试模式诊断代码或专门的单元测试场景非常有用。

          您可以声明一个类似于抽象方法的分部方法,然后在另一个分部类中,当您键入关键字“partial”时,您可以利用 Intellisense 来创建该方法的实现。

          如果您用条件构建语句包围一个部分,那么您可以轻松地切断仅调试或测试代码。在下面的示例中,在 DEBUG 模式下,调用了 LogSomethingDebugOnly 方法,但在发布版本中,就好像该方法根本不存在 - 一种使诊断代码远离生产代码的好方法,无需一堆分支或多个条件编译块。

          // Main Part
          public partial class Class1
          {
              private partial void LogSomethingDebugOnly();
          
              public void SomeMethod()
              {
                  LogSomethingDebugOnly();
                  // do the real work
              }
          }
          
          // Debug Part - probably in a different file
          public partial class Class1
          {
          
              #if DEBUG
          
              private partial void LogSomethingDebugOnly()
              {
                  // Do the logging or diagnostic work
              }
          
              #endif
          }
          

          【讨论】:

          • 我是否必须将方法 LogSomethingDebugOnly() 放入 // Main Part 中,还是仅将方法放入 // Debug Part 中就足够了?
          【解决方案6】:

          LINQ to SQL 充分利用部分类来扩展设计器生成的代码。我认为您通常会发现设计人员创建的代码使用这种分部类模式。

          【讨论】:

            【解决方案7】:

            我发现部分类非常有用。通常它们用于能够扩展自动生成的类。我在一个带有大量单元测试的项目中使用了它们。我的 UT 类具有复杂的依赖关系,在多个类之间分离代码并不是很实用。当然最好使用继承\组合,但在某些情况下,部分类可能会有所帮助。

            【讨论】:

              【解决方案8】:

              如前所述,我也认为这是代码异味。

              如果一个类太大了,需要拆分成更多的文件,意味着它打破了单一职责原则,做了太多的事情。 可以将大类分解为一起合作的小类。

              如果您必须使用部分类或区域来组织代码,请考虑它们是否应该在自己的类中。它增加了可读性,您将获得更多的代码重用。

              【讨论】:

                【解决方案9】:

                也许为时已晚,但请让我也加我的 2 美分:

                *.在处理大型项目时,将一个类分布在单独的文件中允许多个程序员同时处理它。

                *.您可以轻松地为 VS.NET 生成的类编写代码(用于扩展功能)。这将允许您编写自己需要的代码,而不会弄乱系统生成的代码

                【讨论】:

                  【解决方案10】:

                  我现在有一个程序来处理来自客户端的传入文件。它的设置使得每个客户端的代码都在它自己的类库项目中,它知道如何处理客户端选择使用的任何格式。

                  主要代码通过定义库中的类必须实现的相当广泛的接口来使用库(可能应该是几个不同的接口,但现在改变它为时已晚)。有时这涉及到同一个类中的代码比我们通常认为的谨慎得多。部分类允许我们在一定程度上分解它们。

                  【讨论】:

                    【解决方案11】:

                    在相对复杂的用户控件上,我将事件处理的东西放在一个文件中,将绘画和属性放在另一个文件中。部分类对此非常有用,通常类的这些部分是相对独立的,能够并排编辑绘画和事件处理非常好。

                    【讨论】:

                      【解决方案12】:

                      几年前我参与了一个项目,我们有一个类型化的 DataSet 类,其中包含大量代码:DataTables 中的方法、TableAdapter 中的方法、TableAdapter 实例的声明等等。这是项目的一个巨大的中心点,每个人都必须经常进行工作,并且对于部分类代码文件存在很多源代码控制争用。

                      所以我将代码文件分成修复或六个部分类文件,按功能分组,这样我们就可以处理较小的部分,而不必在每次需要更改一些小东西时锁定整个文件。

                      (当然,我们也可以通过不使用独占锁定源代码控制系统来解决问题,但这是另一个问题。)

                      【讨论】:

                        【解决方案13】:

                        一般来说,我认为这是一种代码异味。

                        如果您的类如此复杂,那么它可能可以分解成更小的可重用组件。

                        或者这意味着没有继承层次结构应该有一个。

                        对于代码生成场景,这很好,但我认为代码生成是另一种代码味道。

                        【讨论】:

                        • 你的意思是说使用Windows Forms设计器、Entity Framework的设计器等都是代码异味?它们当然是使用中的代码生成案例。
                        • 是的,MS 似乎同意。 WPF 使用声明性语法而不是拖放。实体框架已切换到代码优先模型。
                        【解决方案14】:

                        我在游戏中迟到了......但只是我的 2 美分......

                        一种用途可能是将现有遗留代码库中的现有上帝类重构为多个部分类。它可以提高代码的可发现性——如果包含部分类的文件名遵循正确的命名约定。这也可以减少源代码存储库 - 在一定程度上解析和合并。

                        理想情况下,一个上帝类应该被分解成多个小类——每个小类都有单一的职责。有时执行大中型重构会造成破坏。在这种情况下,部分类可以提供暂时的缓解。

                        【讨论】:

                          【解决方案15】:

                          更正,正如马特指出的那样,部分的双方都需要在同一个程序集中。 我的错。

                          【讨论】:

                            【解决方案16】:

                            我在数据访问层中使用它。生成的类如映射器和查询部分。如果我需要添加一个映射器方法,例如执行未生成的精美加载,我将其添加到自定义类中。

                            最后,在业务层中使用数据层的程序员只能看到一个类具有他或她需要的所有功能。如果数据源发生变化,可以轻松生成通用部分,而无需覆盖自定义内容。

                            【讨论】:

                              【解决方案17】:

                              我刚刚发现部分类的用途。我有一个 [DataContract] 类,用于将数据传递给客户端。我希望客户端能够以特定方式(文本输出)显示类。所以我创建了一个部分类并覆盖了 ToString 方法。

                              【讨论】:

                                【解决方案18】:

                                有时您可能会发现非常旧的代码在工作,这可能使得在不破坏现有代码的情况下重构为不同的元素几乎是不可能的。

                                当您没有选择或没有时间创建更真实的架构时,分部类可以非常容易地在需要的地方分离逻辑。这允许现有代码继续使用相同的架构,同时您更接近更具体的架构。

                                【讨论】:

                                  【解决方案19】:

                                  您之前使用过#region 部分的任何地方都可能更适合作为部分类中的单独文件。

                                  我个人将部分类用于大型类,其中静态成员放在一个文件中,实例成员放在另一个文件中。

                                  【讨论】:

                                    【解决方案20】:

                                    编辑:Visual Studio 的 DSL 工具使用部分类。

                                    因此,这是许多自动生成的代码使用的功能。 自动生成的代码不使用#region,而是转到一个文件,而用户代码(也称为自定义代码)转到另一个文件,甚至在不同的目录中,这样开发人员就不会对这么多无意义的文件感到困惑。

                                    有这个选项很好,你可以结合 - 但不强制使用 - 与继承

                                    此外,将某些类的逻辑分离到几个目录中会很方便。当然,对于机器来说也是一样,只是增强了用户的可读性体验。

                                    【讨论】:

                                      猜你喜欢
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2015-03-13
                                      • 2010-10-19
                                      相关资源
                                      最近更新 更多