什么时候适合使用C#部分类?

Ast*_*rix 491 c# architecture class

我想知道是否有人能够概述我为什么要使用它们以及我在这个过程中会获得什么好处.

Jar*_*Par 404

部分类的最大用途是使代码生成器/设计者的生活更轻松.部分类允许生成器简单地发出他们需要发出的代码,并且他们不必处理用户对文件的编辑.用户同样可以通过使用第二个分类来自由地使用新成员来注释该类.这为分离关注点提供了一个非常干净的框架.

更好的方法是看看设计师在部分课程之前的运作方式.WinForms设计人员会吐出一个区域内的所有代码,其中包含有关不修改代码的强烈措辞.它必须插入各种启发式方法才能找到生成的代码以供以后处理.现在它可以简单地打开designer.cs文件,并且高度自信它只包含与设计器相关的代码.

  • 诱惑给你一个让我做噩梦的事情,关于在部分课程之前有多糟糕的事情:) (67认同)
  • 一旦我编写了一个产生超过36K行的代码生成器(或者可能更多,我没有完全记得),并且在打开源代码时我的编辑器被阻止了.部分类允许我查看生成的代码而不需要4 GB的RAM. (17认同)
  • @Jon :),我想我们都做过那些噩梦. (9认同)
  • 我会说这是生产代码中部分类的唯一用途.虽然我接受它可能对重构很有用. (6认同)
  • @Gordon - HumerGu的答案是另一个我认为很难反驳的答案.部分类可以非常方便地在C#中实现接口,并使接口成员与类成员保持清晰分离:http://stackoverflow.com/questions/3601901/why-use-partial-classes/3602871#3602871 (5认同)
  • @Gordon,允许嵌套类包含在单独的代码文件中也非常好. (3认同)

rel*_*ope 247

另一个用途是拆分不同接口的实现,例如:

partial class MyClass : IF1, IF2, IF3
{
    // main implementation of MyClass
}


partial class MyClass
{
    // implementation of IF1
}

partial class MyClass
{
    // implementation of IF2
}
Run Code Online (Sandbox Code Playgroud)

  • 一个很好的用途,但一个坏的例子.为什么哦为什么要定义一个部分类的所有接口并在其他部分类中实现相同的接口? (14认同)
  • 好点子!这是我以前做过的并且被遗忘的东西,但绝对是保持界面成员清晰可见的好方法(特别是在C#中,因为VB.NET使用`Implements`关键字来表示属于接口的方法) (4认同)
  • 哈,我只是查看这个问题,看看分离接口实现是否是部分类的标准用法.很高兴看到其他人认为这是一个好主意.我同意@inkredibl关于将接口定义与实现它的部分类放在一起. (4认同)
  • 如何根据类的声明顺序知道哪一个用于IF1或IF2 .. (3认同)
  • 非常好的一点,每个接口都可以由Developer实现,也是**很容易找到接口的实现.** (2认同)
  • 在使用了过度使用了部分代码的代码并亲自进行了试验之后,我个人认为,当不使用部分代码将生成的代码与您自己的代码分开时,应该经过仔细考虑。否则,很容易以跨越多个文件的庞大类结尾。维持这样的课程并不好玩。在使用它之前,您应该考虑是否真的从一个班级中受益。 (2认同)
  • @Shelby Oldfield:Jimbo 正在考虑整个类的“接口”,而不是类实现的接口。区分“类的接口”(世界可见的所有内容)和“接口定义”(方法形式的契约)。因此,如果一个类实现了许多接口,那么该类本身肯定有一个“臃肿的接口”,正如 Jimbo 所说 (2认同)

STW*_*STW 161

除了其他答案......

我发现它们有助于作为重构神级的踏脚石.如果一个类有多个职责(特别是如果它是一个非常大的代码文件)那么我发现将每个责任的1x部分类添加为组织然后重构代码的第一遍是有益的.

这有很大帮助,因为它可以帮助使代码更具可读性而不会实际影响执行行为.它还可以帮助确定何时责任易于重构或与其他方面紧密纠缠在一起.

但是 - 要清楚 - 这仍然是错误的代码,在开发结束时,你仍然需要每个类一个责任(不是每个部分类).这只是一块踏脚石:)

  • 非常好:"......在开发结束时,你仍然需要每班一个责任(**不**每个部分班级)......" (23认同)
  • 对我来说,这不是一种好的编码风格,但可以让糟糕的代码看起来更好。 (2认同)

hel*_*hab 82

  1. 多个开发人员使用部分类多个开发人员可以轻松地在同一个类上工作.
  2. 代码生成器部分类主要由代码生成器使用,以将不同的关注点分开
  3. 使用部分类的部分方法您也可以定义部分方法,开发人员可以简单地定义方法,而其他开发人员可以实现该方法.
  4. 仅部分方法声明即使代码使用方法声明进行编译,并且如果不存在该方法的实现,编译器也可以安全地删除该段代码,并且不会发生编译时错误.

    验证点4.只需创建一个winform项目并在Form1构造函数后面包含这一行并尝试编译代码

    partial void Ontest(string s);
    
    Run Code Online (Sandbox Code Playgroud)

在实现部分类时,需要考虑以下几点: -

  1. 在部分类的每个部分中使用partial关键字.
  2. 部分类的每个部分的名称应该相同,但是部分类的每个部分的源文件名可以不同.
  3. 部分类的所有部分都应位于同一名称空间中.
  4. 部分类的每个部分应该在同一个程序集或DLL中,换句话说,您不能在不同的类库项目的源文件中创建部分类.
  5. 部分类的每个部分必须具有相同的可访问性.(即:私人,公共或受保护)
  6. 如果在部分类上继承类或接口,则该部分类的所有部分都将继承该类或接口.
  7. 如果部分类的一部分被密封,则整个类将被密封.
  8. 如果部分类的一部分是抽象的,则整个类将被视为抽象类.


Jus*_*ner 55

一个很好的用途是将生成的代码与属于同一类的手写代码分开.

例如,由于LINQ to SQL使用了部分类,因此您可以编写自己的某些功能实现(如多对多关系),并且在重新生成代码时,这些自定义代码不会被覆盖.

WinForms代码也是如此.所有Designer生成的代码都放在一个您通常不接触的文件中.您手写的代码放在另一个文件中.这样,当您在Designer中更改某些内容时,您的更改不会被吹走.


小智 20

确实,Partial Class用于自动代码生成,一个用途可以维护一个可能有数千行代码的大类文件.你永远不会知道你的班级可能最终有10万行,你不想创建一个具有不同名称的新类.

public partial class Product
{
    // 50 business logic embedded in methods and properties..
}

public partial class Product
{
    // another 50 business logic embedded in methods and properties..
}
//finally compile with product.class file.
Run Code Online (Sandbox Code Playgroud)

另一种可能的用途可能是,不止一个开发人员可以在同一个类上工作,因为它们存储在不同的地方.人们可能会笑,但你永远不会知道它有时会很少.

Product1.cs

public partial class Product
{
    //you are writing the business logic for fast moving product
}
Run Code Online (Sandbox Code Playgroud)

Product2.cs

public partial class Product
{
    // Another developer writing some business logic...
}
Run Code Online (Sandbox Code Playgroud)

希望它有意义!


小智 12

在处理大型课程时保持一切尽可能干净,或者在团队中工作时,您可以在不覆盖(或始终提交更改)的情况下进行编辑


cle*_*tus 11

部分类的主要用途是生成代码.如果查看WPF(Windows Presentation Foundation)网络,可以使用标记(XML)定义UI.该标记被编译为部分类.您使用自己的部分类填写代码.


Viv*_*rav 11

部分类跨越多个文件.

How can you use the partial modifier on a C# class declaration?

使用partial,您可以将类物理地分成多个文件.

这通常由代码生成器完成.

使用普通的C#类,您无法在同一项目中的两个单独文件中声明一个类.

但是使用partial修饰符,你可以.

如果通常编辑一个文件而另一个文件是机器生成的或很少编辑,则此功能非常有用.

An Example will clear your concept.

class Program
{
    static void Main()
    {
    A.A1();
    A.A2();
    }
}

//Contents of file A1.cs: C#

using System;

partial class A
{
    public static void A1()
    {
    Console.WriteLine("A1");
    }
}

//Contents of file A2.cs: C#

using System;

partial class A
{
    public static void A2()
    {
    Console.WriteLine("A2");
    }
}

Output

A1
A2
Run Code Online (Sandbox Code Playgroud)

这里需要部分.

If you remove the partial modifier, you will get an error containing this text: [The namespace '<global namespace>' already contains a definition for 'A'].

提示: 要解决此问题,您可以使用partial关键字,也可以更改其中一个类名.

How does the C# compiler deal with partial classes?

如果您反汇编上述程序,您将看到文件A1.cs和A2.cs被删除.

你会发现A级存在.

IL反汇编程序所以:类A将在同一代码块中包含方法A1和A2.这两个类合并为一个.

A1.cs和A2.cs的编译结果:C#

internal class A
{
    // Methods
    public static void A1()
    {
    Console.WriteLine("A1");
    }

    public static void A2()
    {
    Console.WriteLine("A2");
    }
}
Run Code Online (Sandbox Code Playgroud)

摘要

部分类可以简化某些C#编程情况.

在创建Windows窗体/ WPF程序时,它们通常在Visual Studio中使用.

机器生成的C#代码是独立的.

或者你可以在这里找到整个描述.

  • 很好的例子和详细记录. (2认同)

3Da*_*ave 8

如果你有一个足够大的类,不适合有效的重构,将它分成多个文件有助于保持组织有序.

例如,如果您有一个包含讨论论坛和产品系统的站点的数据库,并且您不想创建两个不同的提供者类(与代理类不同,只是为了清楚),您可以在不同的文件中创建一个单独的类,比如

MyProvider.cs - 核心逻辑

MyProvider.Forum.cs - 专门针对论坛的方法

MyProvider.Product.cs - 产品的方法

这只是保持组织有序的另一种方式.

此外,正如其他人所说,它是将方法添加到生成的类的唯一方法,而不会冒下次重新生成类时销毁添加项的风险.这对模板生成的(T4)代码,ORM等很方便.

  • @supercat - 我完全理解,但应该清理那种意大利面**.我有很多伤疤来清理那种类型的代码,并且永远不会主张将其抛弃.这些类型的混乱保证不断产生问题,与忽略问题相比,长期收益是巨大的.像这样的代码没有"闻到",它就像一个垃圾场. (4认同)
  • 我会提倡将partial作为重构的踏脚石(我的答案的全部要点),但不会建议将它们作为写清洁代码的实际解决方案.如果一个部分课程与该课程的其他问题完全分开,那么为什么不加倍努力将其推广到一个独立的课程呢? (2认同)
  • 顺便说一句,这些天我一直在尝试修改Roslyn,并且它广泛使用了部分类。Roslyn中的很多主要类被定义为多个文件中的部分类。Roslyn是由至少我认为是非常聪明的C#程序员的人编写的。 (2认同)

STW*_*STW 8

作为预编译器指令的替代方案.

如果您使用预编译器指令(即#IF DEBUG),那么您最终会得到与您的实际版本代码混合的一些看起来很难看的代码.

您可以创建一个单独的部分类来包含此代码,并将整个部分类包装在一个指令中,或者省略该代码文件被发送到编译器(实际上是这样做).


dee*_*gee 7

大多数人认为partial应该只用于具有生成的代码文件的类或接口。我不同意,这就是原因。

举个例子,让我们看看 C# System.Math 类……那是class。我不会尝试将 70 多种方法都塞进同一个代码文件中。维持下去将是一场噩梦。

将每个数学方法放入单独的部分类文件中,并将所有代码文件放入项目中的 Math 文件夹中,这样组织起来会更加清晰。

对于具有大量不同功能的许多其他类,同样可以/将适用。例如,用于管理 PrivateProfile API 的类可能会受益于在单个项目文件夹中拆分为一组干净的部分类文件。

就个人而言,我还将大多数人称为“帮助程序”或“实用程序”类的内容拆分为每个方法或方法功能组的单独部分文件。例如,在一个项目中,字符串助手类有近 50 个方法。即使使用区域,那也将是一个长而笨重的代码文件。为每个方法使用单独的部分类文件会更容易维护。

在执行此操作时,我会小心使用部分类并在整个项目中保持所有代码文件布局一致。例如,将任何类公共枚举和类私有成员放入文件夹中的 Common.cs 或类似命名的文件中,而不是将它们分散到文件中,除非它们仅特定于包含它们的部分文件。

请记住,当您将一个类拆分为单独的文件时,您也无法使用文本编辑器拆分栏,该拆分栏可让您同时查看当前文件的两个不同部分。


Fra*_*ori 6

服务引用是另一个示例,其中部分类可用于将生成的代码与用户创建的代码分开.

您可以"扩展"服务类,而不会在更新服务引用时覆盖它们.


Sri*_*thy 6

我看到的另一个用途是,

扩展关于数据访问逻辑的大抽象类,

我有各种文件名称Post.cs,Comment.cs,Pages.cs ...

in Post.cs 

public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of post..
}


in Comment.cs 

public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of comment..
}

in Pages.cs 

public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of Pages..
}
Run Code Online (Sandbox Code Playgroud)