ChatGPT解决这个技术问题 Extra ChatGPT

When is it appropriate to use C# partial classes?

I was wondering if someone could give me an overview of why I would use them and what advantage I would gain in the process.


D
Damien_The_Unbeliever

The biggest use of partial classes is to make life easier for code generators / designers. Partial classes allow the generator to simply emit the code they need to emit and they do not have to deal with user edits to the file. Users are likewise free to annotate the class with new members by having a second partial class. This provides a very clean framework for separation of concerns.

A better way to look at it is to see how designers functioned before partial classes. The WinForms designer would spit out all of the code inside of a region with strongly worded comments about not modifying the code. It had to insert all sorts of heuristics to find the generated code for later processing. Now it can simply open the designer.cs file and have a high degree of confidence that it contains only code relevant to the designer.


I'd go as far to say that this is the only use for partial classes in production code. Although I accept it may be useful for refactoring.
@Gordon, it's also very nice for allowing a nested class to be contained in a separate code file.
@Gordon -- HumerGu's answer is another that I think is fairly hard to argue against. Partial classes can be very handy for implementing interfaces in C#, and keeping the interface members clearly seperate from the class-members: stackoverflow.com/questions/3601901/why-use-partial-classes/…
It's great also for segmenting conditionally-compiled code. Eg MyClassCore.cs, MyClassUtility.cs, MyClassProduction.cs.
T
Tripp Kinetics

Another use is to split the implementation of different interfaces, e.g:

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


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

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

Good point! It's something I've done before and forgotten about, but is definately a nice way to keep the interface members clearly visible (especially in C#, since VB.NET uses the Implements keyword to denote a method belongs to an interface)
very nice point, each of the interface can be Implemented by a Developer, Also it's good way to find interface's implementation easily.
how does one know which one is for IF1, or IF2 .. by the order of declaration of classes ?
Ha, I just looked up this question to see if separating interface implementations was a standard use for partial classes. Glad to see that others see it as a good idea. I agree with @inkredibl about putting the interface definition together with the partial class that implements it.
After working with code overusing partial, and experiment with it my self, I personally think that you should use partial after thorough consideration when not using it for separating the generated code from your own. Otherwise it is easy to end up with a huge class spanning through several files; and it is not fun to maintain such class. Before using this, you should consider whether it really benefits from being one class.
S
STW

Aside from the other answers...

I've found them helpful as a stepping-stone in refactoring god-classes. If a class has multiple responsibilities (especially if it's a very large code-file) then I find it beneficial to add 1x partial class per-responsibility as a first-pass for organizing and then refactoring the code.

This helps greatly because it can help with making the code much more readable without actually effecting the executing behavior. It also can help identify when a responsibility is easy to refactor out or is tightly tangled with other aspects.

However--to be clear--this is still bad code, at the end of development you still want one responsibility per-class (NOT per partial class). It's just a stepping-stone :)


To me, it's not a good coding style, but can make bad codes looks better.
I fully agree with this. It is a good stepping stone towards fixing bad code. A god class is a god class weather it is spread across multiple files or not.
S
Sizons

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);

Here are some points to consider while implementing partial classes:-

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.


Is there any problem edit a partial class created from Entity Framework? I wish to change some classes names, created from a table.
I have the same concerns. I want to know the benefits "If any" that a partial class has when building models that Entity Framework will essentially use to build my database from a Code First perspective/approach/implementation... what have you.
@JimBalter Kindly go through this link msdn.microsoft.com/en-us/library/6b0scde8(v=vs.110).aspx. This states that if there is no implementation present compiler will remove the piece of code and no compile time error will be received.
If you inherit a class or interface on a partial class then it is inherited by all parts of that partial class.
J
Justin Niessner

One great use is separating generated code from hand-written code that belong in the same class.

For example since LINQ to SQL uses partial classes you can write your own implementation of certain pieces of functionality (like Many-to-Many relationships) and those pieces of custom code won't get overwritten when you re-generate the code.

The same goes for WinForms code. All the Designer generated code goes in one file that you generally don't touch. Your hand-written code goes in another file. That way, when you change something in Designer, your changes don't get blown away.


R
Rohit416

It is true that Partial Class is used in auto code generation, one use can be maintaining a large class file which might have thousand lines of code. You never know your class might end up with 10 thousand lines and you don't want to create a new class with different name.

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.

Another possible use could be that more than one developer can work on the same class as they are stored at different places. People might laugh but you never know it can be handful sometimes.

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...
}

Hope it makes sense!


C
CarenRose

Partial classes span multiple files.

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

With partial classes, you can physically separate a class into multiple files. This is often done by code generators.

Example

With normal C# classes, you cannot declare a class in two separate files in the same project. But with the partial modifier, you can.

This is useful if one file is commonly edited and the other is machine-generated or rarely edited.

Here's an example to clarify:

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

Partial is required here.

If you remove the partial modifier, you will get an error containing this text:

[The namespace '' already contains a definition for 'A'].

Tip:

To fix this, you can either use the partial keyword, or change one of the class names.

How does the C# compiler deal with partial classes?

If you disassemble the above program (using IL Disassembler), you will see that the files A1.cs and A2.cs are eliminated. You will find that the class A is present.

Class A will contain the methods A1 and A2 in the same code block. The two classes were merged into one.

Compiled result of A1.cs and A2.cs: C#

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

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

Summary

Partial classes can simplify certain C# programming situations.

They are often used in Visual Studio when creating Windows Forms/WPF programs.

The machine-generated C# code is separate.

Or You could find the whole description here.


佚名

keep everything as clean as possible when working with huge classes, or when working on a team, you can edit without overriding (or always commiting changes)


c
cletus

The main use for partial classes is with generated code. If you look at the WPF (Windows Presentation Foundation) network, you define your UI with markup (XML). That markup is compiled into partial classes. You fill in code with partial classes of your own.


S
STW

As an alternative to pre-compiler directives.

If you use pre-compiler directives (namely #IF DEBUG) then you end up with some gnarly looking code intermingled with your actual Release code.

You can create a seperate partial-class to contain this code, and either wrap the entire partial class in a directive, or omit that code-file from being sent to the compiler (effectively doing the same).


Monogame uses this strategy.
3
3Dave

If you have a sufficiently large class that doesn't lend itself to effective refactoring, separating it into multiple files helps keep things organized.

For instance, if you have a database for a site containing a discussion forum and a products system, and you don't want to create two different providers classes (NOT the same thing as a proxy class, just to be clear), you can create a single partial class in different files, like

MyProvider.cs - core logic

MyProvider.Forum.cs - methods pertaining specifically to the forum

MyProvider.Product.cs - methods for products

It's just another way to keep things organized.

Also, as others have said, it's about the only way to add methods to a generated class without running the risk of having your additions destroyed the next time the class is regenerated. This comes in handy with template-generated (T4) code, ORMs, etc.


I would advocate partial's as a stepping stone towards refactoring (the whole point of my answer), but wouldn't suggest them as an actual solution to writting clean code. If a partial class is cleanly seperated from other concerns of the class, then why not put in the extra small effort to promote it to a standalone class?
@STW: It may be that many object instances are created and used for various tasks. Separating the various tasks into different classes would require tracking down which instances were used for which tasks--potentially a much larger undertaking than merely moving blocks of code between source modules.
@supercat -- I understand entirely, but cleaning up that kind of spaghetti should be undertaken. I've got plenty of scars from cleaning up exactly that type of code, and would never advocate leaving it behind. Those types of messes are guaranteed to continuously create problems, and the long-term payoff is huge compared to just ignoring the problem. Code like that doesn't "smell", it reeks like a garbage dump.
@supercat -- I tried to qualify that with "If a partial is cleanly separated from other concerns ... then it's a small effort". Going through the pain of untangling will usually save big in long-term maintenance, if not Rogaine
Incidentally, I'm playing around with trying to modify Roslyn these days, and it is written with extensive use of partial classes. Lots and lots of the major classes in Roslyn are defined as partial classes in multiple files. And Roslyn was written by people who I, at least, consider to be very clever C# programmers.
d
deegee

Most people remark that partial should only be used for a class that has a generated code file or for interfaces. I disagree, and here is why.

For one example, let's look at the C# System.Math class... that's class. I would not attempt to stuff 70+ methods all into the same single code file. It would be a nightmare to maintain.

Placing each math method into individual partial class files, and all code files into a Math folder in the project, would be significantly cleaner organization.

The same could/would hold true for many other classes that have a large amount of diverse functionality. For example a class for managing the PrivateProfile API might benefit by being split into a clean set of partial class files in a single project folder.

Personally, I also split what most people call "helper" or "utility" classes into individual partial files for each method or method functional group. For example on one project the string helper class has almost 50 methods. That would be a long unwieldy code file even using regions. It is significantly easier to maintain using individual partial class files for each method.

I would just be careful using partial classes and keep all code file layout consistent throughout the project when doing this. Such as placing any class public enums and class private members into a Common.cs or similarly named file in the folder, instead of spreading them out across the files unless they are specific to only the partial file they are contained in.

Keep in mind that when you split a class into separate files you also lose the ability to use the text editor splitter bar that lets you view two different sections of a current file simultaneously.


F
Francesco De Vittori

Service references are another example where partial classes are useful to separate generated code from user-created code.

You can "extend" the service classes without having them overwritten when you update the service reference.


S
Srinivas Reddy Thatiparthy

Another use i saw is,

Extending a big abstract class regarding data access logic ,

i have various files with names 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..
}

s
supercat

Partial classes make it possible to add functionality to a suitably-designed program merely by adding source files. For example, a file-import program could be designed so that one could add different types of known files by adding modules that handle them. For example, the main file type converter could include a small class:

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

Each module that wishes to register one or more types of file converter could include something like:

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

Note that the main file converter class isn't "exposed"--it just exposes a little stub class that add-in modules can hook to. There is a slight risk of naming conflicts, but if each add-in module's "register" routine is named according to the type of file it deals with, they probably shouldn't pose a problem. One could stick a GUID in the name of the registration subroutine if one were worried about such things.

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.

One could, without using partial classes, have a bit of code somewhere within the main file converter class, which looked like:

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

but adding another converter module would require going into that part of the converter code and adding the new converter to the list. Using partial methods, that is no longer necessary--all converters will get included automatically.


it works, but a simple plugin-system to dynamically load these modules would be much nicer and would help eliminate the risk of modules corrupting one another (it could load the modules at runtime rather than requiring a recompile)
The risk of the modules corrupting one another can be pretty well minimized if they don't do anything with the zz_ class except hook a Register event and call a routine to register themselves. What risks do you see that wouldn't exist with a plug-in? Plug-ins are great if the end user is expected to "plug in" new modules. Sometimes, though, one wants to put all the functionality in a single exe. Being able to plug in source files without having to manually add a reference to the newly-added files can be handy.
the risk is fairly well contained in your line "...if they don't do anything [...] except...", the security and stability rides entirely on the developer following convention, and provides 0% assurance. If your use-case is to have them compiled in (perfectly valid, just needs to be a conscience trade-off) then why not just have the modules defined in seperate classes and implementing some IModule interface?
It sounds like a case of being "clever" gone bad. These aren't "modules", they are single class with many behaviors and responsibilities rolled into one at compile-time. There's a lot of better ways of doing this--you could use Reflection to scan the compiled assembly for classes which implement IModule, you could use a plugin-framework like MEF (just one of many), etc etc.
J
Jay

Partial classes recently helped with source control where multiple developers were adding to one file where new methods were added into the same part of the file (automated by Resharper).

These pushes to git caused merge conflicts. I found no way to tell the merge tool to take the new methods as a complete code block.

Partial classes in this respect allows for developers to stick to a version of their file, and we can merge them back in later by hand.

example -

MainClass.cs - holds fields, constructor, etc

MainClass1.cs - a developers new code as they implement

MainClass2.cs - is another developers class for their new code.


E
Eli

From MSDN:

1.At compile time, attributes of partial-type definitions are merged. For example, consider the following declarations:

[SerializableAttribute]
partial class Moon { }

[ObsoleteAttribute]
partial class Moon { }

They are equivalent to the following declarations:

[SerializableAttribute]
[ObsoleteAttribute]
class Moon { }

The following are merged from all the partial-type definitions:

XML comments

interfaces

generic-type parameter attributes

class attributes

members

2.Another thing, nested partial classes can be also partial:

partial class ClassWithNestedClass
{
    partial class NestedClass { }
}

partial class ClassWithNestedClass
{
    partial class NestedClass { }
}

s
shashi

Here is a list of some of the advantages of partial classes.

You can separate UI design code and business logic code so that it is easy to read and understand. For example you are developing an web application using Visual Studio and add a new web form then there are two source files, "aspx.cs" and "aspx.designer.cs" . These two files have the same class with the partial keyword. The ".aspx.cs" class has the business logic code while "aspx.designer.cs" has user interface control definition.

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.

More than one developer can simultaneously write the code for the class.

You can maintain your application better by compacting large classes. Suppose you have a class that has multiple interfaces so you can create multiple source files depending on interface implements. It is easy to understand and maintain an interface implemented on which the source file has a partial class.


C
Craig Wilcox

I find it disturbing that the word 'cohesion' does not appear anywhere in these posts (until now). And I'm also disturbed that anyone thinks enabling or encouraging huge classes and methods is somehow a good thing. If you're trying to understand and maintain a code-base 'partial' sucks.


Ɖ
Ɖiamond ǤeezeƦ

Whenever I have a class that contains a nested class that is of any significant size/complexity, I mark the class as partial and put the nested class in a separate file. I name the file containing the nested class using the rule: [class name].[nested class name].cs.

The following MSDN blog explains using partial classes with nested classes for maintainability: http://blogs.msdn.com/b/marcelolr/archive/2009/04/13/using-partial-classes-with-nested-classes-for-maintainability.aspx


佚名

I know this question is really old but I would just like to add my take on partial classes.

One reason that I personally use partial classes is when I'm creating bindings for a program, especially state machines.

For example, OpenGL is a state machine, there are heaps of methods that can all be changed globally, however, in my experience binding something similar to OpenGL where there are so many methods, the class can easily exceed 10k LOC.

Partial classes will break this down for me and help me with finding methods quickly.


K
Kiran Bheemarti

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 http://www.4guysfromrolla.com/articles/071509-1.aspx


C
Colm Bhandal

I note two usages which I couldn't find explicitly in the answers.

Grouping Class Items

Some developers use comments to separate different "parts" of their class. For example, a team might use the following convention:

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

With partial classes, we can go a step further, and split the sections into separate files. As a convention, a team might suffix each file with the section corresponding to it. So in the above we would have something like: MyClassMembers.cs, MyClassConstructors.cs, MyClassProperties.cs, MyClassMethods.cs.

As other answers alluded to, whether or not it's worth splitting the class up probably depends on how big the class is in this case. If it's small, it's probably easier to have everything in one master class. But if any of those sections get too big, its content can be moved to a separate partial class, in order to keep the master class neat. A convention in that case might be to leave a comment in saying something like "See partial class" after the section heading e.g.:

//Methods - See partial class

Managing Scope of Using statements / Namespace

This is probably a rare occurrence, but there might be a namespace collision between two functions from libraries that you want to use. In a single class, you could at most use a using clause for one of these. For the other you'd need a fully qualified name or an alias. With partial classes, since each namespace & using statements list is different, one could separate the two sets of functions into two separate files.


There are mechanisms to resolve namespace collision, for example, renaming a namespace using using Library1 = The.Namespace.You.Need or global::Root.Of.Namespace
Yeah I suppose that's a weak use case. But it's a little nicer to not have to fully qualify names. More of a nice unintended side effect than a reason for using partial classes.