我想知道是否有人能给我一个概述,为什么我要使用它们,在这个过程中我能获得什么好处。


一个很好的用法是将生成的代码与属于同一类的手写代码分离。

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

WinForms代码也是如此。所有设计器生成的代码都放在一个文件中,您通常不会接触这个文件。手写的代码放到另一个文件中。这样,当您在设计器中更改某些内容时,您所做的更改不会被影响。


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


部分类的最大用途是使代码生成器/设计人员的工作更轻松。部分类允许生成器简单地发出它们需要发出的代码,而不需要处理用户对文件的编辑。用户同样可以通过创建第二个分部类来自由地用新成员注释类。这为关注点分离提供了一个非常清晰的框架。

更好的方法是看看设计器在部分类之前是如何工作的。WinForms设计器会吐出区域内的所有代码,并给出不修改代码的强烈注释。它必须插入各种启发式方法来找到生成的代码,以便稍后进行处理。现在它可以简单地打开designer.cs文件,并有高度的信心它只包含与设计器相关的代码。


如果您有一个足够大的类,而不适合进行有效的重构,那么将它分离到多个文件中有助于保持内容的组织性。

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

——核心逻辑

cs -专门与论坛相关的方法

产品的方法

这是另一种让事情井井有条的方法。

另外,正如其他人所说,这是向生成的类添加方法而不会在下次重新生成类时破坏所添加的方法的唯一方法。这对于模板生成的(T4)代码、orm等非常方便。


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

您可以在更新服务引用时“扩展”服务类,而不必覆盖它们。


除了其他答案之外……

我发现它们可以作为重构神类的垫脚石。如果一个类有多个职责(特别是如果它是一个非常大的代码文件),那么我发现为每个职责添加1x个部分类作为组织和重构代码的第一步是有益的。

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

然而,需要明确的是,这仍然是糟糕的代码,在开发结束时,您仍然希望每个类有一个职责(而不是每个分部类)。这只是一块垫脚石:)


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

如果您使用预编译器指令(即# If DEBUG),那么您最终会看到一些看起来粗糙的代码与实际的Release代码混合在一起。

你可以创建一个单独的分部类来包含这些代码,或者将整个分部类包装在一个指令中,或者省略该代码文件,使其不被发送给编译器(实际上是做同样的事情)。


在处理大型类时,或在团队中工作时,尽可能保持所有内容的干净,您可以在不重写的情况下编辑(或始终提交更改)


通过部分类,只需添加源文件,就可以向适当设计的程序添加功能。例如,可以设计一个文件导入程序,这样就可以通过添加处理文件的模块来添加不同类型的已知文件。例如,主文件类型转换器可以包含一个小类:

Partial Public Class zzFileConverterRegistrar
    Event Register(ByVal mainConverter as zzFileConverter)
    Sub registerAll(ByVal mainConverter as zzFileConverter)
        RaiseEvent Register(mainConverter)
    End Sub
End Class

每个希望注册一个或多个类型的文件转换器的模块可以包括如下内容:

Partial Public Class zzFileConverterRegistrar
    Private Sub RegisterGif(ByVal mainConverter as zzFileConverter) Handles Me.Register
        mainConverter.RegisterConverter("GIF", GifConverter.NewFactory))
    End Sub
End Class

注意,主文件转换器类并没有“公开”——它只是公开了一个小存根类,外接程序模块可以钩子到这个存根类。存在命名冲突的轻微风险,但如果每个外接程序模块的“寄存器”例程是根据它处理的文件类型命名的,那么它们可能不会造成问题。如果担心这样的事情,可以在注册子例程的名称中插入GUID。

Edit/Addendum To be clear, the purpose of this is to provide a means by which a variety of separate classes can let a main program or class know about them. The only thing the main file converter will do with zzFileConverterRegistrar is create one instance of it and call the registerAll method which will fire the Register event. Any module that wants to hook that event can execute arbitrary code in response to it (that's the whole idea) but there isn't anything a module could do by improperly extending the zzFileConverterRegistrar class other than define a method whose name matches that of something else. It would certainly be possible for one improperly-written extension to break another improperly-written extension, but the solution for that is for anyone who doesn't want his extension broken to simply write it properly.

在不使用分部类的情况下,可以在主文件转换器类的某个地方写一些代码,如下所示:

  RegisterConverter("GIF", GifConvertor.NewFactory)
  RegisterConverter("BMP", BmpConvertor.NewFactory)
  RegisterConverter("JPEG", JpegConvertor.NewFactory)

但是添加另一个转换器模块需要进入转换器代码的那一部分,并将新的转换器添加到列表中。使用partial方法,这就不再需要了——所有转换器都会自动包含。


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

partial class MyClass : IF3
{
    // main implementation of MyClass
}


partial class MyClass : IF1
{
    // implementation of IF1
}

partial class MyClass : IF2
{
    // implementation of IF2
}

Partial classes are primarily introduced to help Code generators, so we (users) don't end up loosing all our work / changes to the generated classes like ASP.NET's .designer.cs class each time we regenerate, almost all new tools that generate code LINQ, EntityFrameworks, ASP.NET use partial classes for generated code, so we can safely add or alter logic of these generated codes taking advantage of Partial classes and methods, but be very carefully before you add stuff to the generated code using Partial classes its easier if we break the build but worst if we introduce runtime errors. For more details check this https://web.archive.org/web/20211020111732/https://www.4guysfromrolla.com/articles/071509-1.aspx


我看到的另一个用法是,

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

我有各种文件的名字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..
}

部分类最近帮助了源代码控制,多个开发人员在一个文件中添加新方法,并将其添加到文件的同一部分(由Resharper自动化)。

这些推入git会导致合并冲突。我发现没有办法告诉合并工具把新方法作为一个完整的代码块。

在这方面,部分类允许开发人员坚持他们文件的一个版本,并且我们可以稍后手工将它们合并回去。

的例子,

cs—保存字段、构造函数等 MainClass1.cs—开发人员实现时的新代码 cs -是另一个用于新代码的开发人员类。


的确,Partial Class用于自动代码生成,其中一个用途是维护一个可能有上千行代码的大型类文件。你永远不知道你的类最终会有1万行,你不想用不同的名字创建一个新类。

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.

另一个可能的用途是多个开发人员可以使用同一个类,因为它们存储在不同的地方。人们可能会笑,但你永远不知道有时候情况会很棘手。

Product1.cs

public partial class Product
{
    //you are writing the business logic for fast moving product
}

Product2.cs

public partial class Product
{
    // Another developer writing some business logic...
}

希望这是有意义的!


大多数人认为partial只应该用于生成了代码文件的类或接口。我不同意,原因如下。

举个例子,让我们看看c#系统。数学课…这是类。我不会尝试把70多个方法都塞进同一个代码文件中。维持它将是一场噩梦。

将每个数学方法放入单独的部分类文件中,并将所有代码文件放入项目中的math文件夹中,将显著地使组织更加干净。

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

就我个人而言,我还将大多数人所说的“助手”或“实用工具”类划分为每个方法或方法功能组的单独部分文件。例如,在一个项目中,字符串助手类几乎有50个方法。即使使用区域,这也将是一个冗长而笨拙的代码文件。为每个方法使用单独的部分类文件维护要容易得多。

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

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


Multiple Developer Using Partial Classes multiple developer can work on the same class easily. Code Generator Partial classes are mainly used by code generator to keep different concerns separate Partial Methods Using Partial Classes you can also define Partial methods as well where a developer can simply define the method and the other developer can implement that. Partial Method Declaration only Even the code get compiled with method declaration only and if the implementation of the method isn't present compiler can safely remove that piece of code and no compile time error will occur. To verify point 4. Just create a winform project and include this line after the Form1 Constructor and try to compile the code partial void Ontest(string s);

以下是在实现分部类时需要考虑的几点

Use partial keyword in each part of partial class. The name of each part of partial class should be the same but the source file name for each part of partial class can be different. All parts of a partial class should be in the same namespace. Each part of a partial class should be in the same assembly or DLL, in other words you can't create a partial class in source files from a different class library project. Each part of a partial class must have the same accessibility. (i.e: private, public or protected) If you inherit a class or interface on a partial class then it is inherited by all parts of that partial class. If a part of a partial class is sealed then the entire class will be sealed. If a part of partial class is abstract then the entire class will be considered an abstract class.


分部类跨越多个文件。

如何在c#类声明中使用分部修饰符?

使用部分类,您可以将一个类物理地分离到多个文件中。这通常由代码生成器完成。

例子

对于普通的c#类,您不能在同一个项目中的两个独立文件中声明一个类。但是对于部分修饰语,你可以。

如果一个文件经常被编辑,而另一个文件是机器生成的或很少被编辑,这是很有用的。

这里有一个例子来说明:

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

A1.cs文件内容:c#

using System;

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

A2.cs文件内容:c#

using System;

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

输出:

A1
A2

这里需要Partial。

如果你删除了部分修饰符,你将得到一个包含以下文本的错误:

[命名空间'<全局命名空间>'已经包含' a '的定义]。

Tip:

要解决这个问题,可以使用partial关键字,或者更改其中一个类名。

c#编译器如何处理部分类?

如果你分解上面的程序(使用IL Disassembler),你会看到文件A1.cs和A2.cs被删除了。你会发现A类出现了。

类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");
    }
}

总结

部分类可以简化某些c#编程情况。 当创建Windows窗体/WPF程序时,通常在Visual Studio中使用它们。 机器生成的c#代码是独立的。 或者你可以在这里找到完整的描述。


下面列出了部分类的一些优点。

您可以分离UI设计代码和业务逻辑代码,以便易于阅读和理解。例如,你正在使用Visual Studio开发一个web应用程序,并添加一个新的web表单,然后有两个源文件,“aspx.cs”和“aspx.designer.cs”。这两个文件具有具有partial关键字的相同类。".aspx.cs"类有业务逻辑代码,而"aspx.designer.cs"有用户界面控件定义。

When working with automatically generated source, the code can be added to the class without having to recreate the source file. For example you are working with LINQ to SQL and create a DBML file. Now when you drag and drop a table it creates a partial class in designer.cs and all table columns have properties in the class. You need more columns in this table to bind on the UI grid but you don't want to add a new column to the database table so you can create a separate source file for this class that has a new property for that column and it will be a partial class. So that does affect the mapping between database table and DBML entity but you can easily get an extra field. It means you can write the code on your own without messing with the system generated code.

多个开发人员可以同时为类编写代码。

压缩大型类可以更好地维护应用程序。假设您有一个具有多个接口的类,因此您可以根据接口实现创建多个源文件。理解和维护源文件具有部分类的接口是很容易的。


从MSDN:

1.在编译时,合并部分类型定义的属性。例如,考虑以下声明:

[SerializableAttribute]
partial class Moon { }

[ObsoleteAttribute]
partial class Moon { }

它们等价于以下声明:

[SerializableAttribute]
[ObsoleteAttribute]
class Moon { }

以下是所有部分类型定义的合并:

XML注释 接口 泛型类型参数属性 类属性 成员

2.另外,嵌套的分部类也可以是分部类:

partial class ClassWithNestedClass
{
    partial class NestedClass { }
}

partial class ClassWithNestedClass
{
    partial class NestedClass { }
}

每当我有一个类,其中包含一个具有重要大小/复杂性的嵌套类时,我将该类标记为partial,并将嵌套类放在一个单独的文件中。我使用规则命名包含嵌套类的文件:[class name]。[嵌套类名].cs。

下面的MSDN博客解释了如何使用带有嵌套类的部分类来实现可维护性:http://blogs.msdn.com/b/marcelolr/archive/2009/04/13/using-partial-classes-with-nested-classes-for-maintainability.aspx


我知道这个问题很老了,但我想补充一下我对部分课程的看法。

我个人使用部分类的一个原因是当我为程序创建绑定时,尤其是状态机。

例如,OpenGL是一个状态机,有很多方法都可以全局更改,然而,根据我的经验,绑定类似于OpenGL的东西,其中有很多方法,类很容易超过10k LOC。

部分类将为我分解这个问题,并帮助我快速找到方法。


我注意到两个用法,我在答案中没有明确找到。

分类项目分组

一些开发人员使用注释来分离类的不同“部分”。例如,一个团队可能使用以下约定:

public class MyClass{  
  //Member variables
  //Constructors
  //Properties
  //Methods
}

对于分部类,我们可以更进一步,将部分分割到单独的文件中。按照惯例,团队可以在每个文件后面加上与之对应的部分。所以在上面我们会有这样的东西:MyClassMembers.cs, MyClassConstructors.cs, MyClassProperties.cs, MyClassMethods.cs。

正如其他答案所暗示的那样,是否值得将班级分开可能取决于在这种情况下班级的规模。如果它很小,那么把所有东西都放在一个大师班可能会更容易。但是,如果这些部分中的任何一部分太大,它的内容可以移动到一个单独的分部类中,以保持主类的整洁。在这种情况下,惯例可能是在节标题后留下类似“See partial class”的注释,例如:

//Methods - See partial class

管理使用语句/命名空间的范围

这种情况可能很少发生,但是来自您想要使用的库的两个函数之间可能会发生名称空间冲突。在单个类中,最多只能为其中一个使用using子句。对于另一种,您需要一个完全限定的名称或别名。对于部分类,由于每个名称空间& using语句列表都不同,因此可以将两组函数分离到两个单独的文件中。


我发现令人不安的是,“凝聚力”这个词在这些帖子中没有出现(直到现在)。 我也很不安,有人认为启用或鼓励大型类和方法在某种程度上是件好事。 如果你试图理解和维护代码基础的“部分”,那就糟透了。