76

In my understanding, the partial keyword does nothing but allow a class to be split between several source files. Is there any reason to do this other than for code organization? I've seen it used for that in generated UI classes.

It seems a poor reason to create a whole keyword. If a class is big enough to require multiple files, it probably is doing too much. I thought that perhaps you could use it to partially define a class for another programmer somewhere to complete, but it would be better to make an abstract class.

6
  • 10
    It's not really a "whole keyword", either. It's a contextual keyword. partial only means something when it comes before class. You can use it as an identifier name in other parts of the code, etc. Apr 26, 2011 at 20:35
  • 4
    If you use them, and it's not for generated code, I hate you. Not you personally, but you generally. I hate hunting down code through partial classes. Apr 26, 2011 at 20:36
  • 3
    It's not hard to "hunt down code", all the class methods still show up in the drop down in VS, regardless of which part of the partial you are looking at. Other code navigation works just fine too (either "clever" R# style navigation or good old shift-ctrl-f
    – Steve
    Apr 27, 2011 at 8:39
  • 2
    It's a misunderstanding that partial classes have to be in seperate files.
    – Bart
    Jul 13, 2011 at 8:04

9 Answers 9

115

It is very useful in every scenario where one part of class is generated by some custom tool because it allows you to adding custom logic to generated code without inheriting the generated class. Btw. there are also partial methods for the same reason.

It is not only about UI but also other technologies like Linq-To-Sql or Entity Framework use this quite heavily.

6
  • 46
    Also, it lets you keep your code under version control while leaving the generated code out of version control. Apr 26, 2011 at 19:58
  • 3
    Good point, I've never thought of that. I've only seen it abused in practice though. A way for (lousy) programmers to keep the file size manageable. Apr 26, 2011 at 20:39
  • 1
    The best examples I've used are: a) for Linq to SQL data contexts where you want to extend the classes; b) to extend classes passed from web services. In neither case is this an abuse nor is it a means to keep file sizes manageable... I'd be radically unhappy to see it used in that manner (and would take steps...)
    – Murph
    Apr 26, 2011 at 21:01
  • 3
    WinForm classes use it to hide all the designer code creating controls (especially important because the designer likes to randomly reorder all the code it creates resulting in huge messes when diff/blaming), and if you're working with XML, the XSD tool can create partial classes off the schema file again allowing you to separate your code from the auto generated sort. Feb 6, 2013 at 21:27
  • 2
    @MartinWickman not necessarily lousy. It's a good starting point for refactoring God objects in legacy code. Try to clear the landscape up by splitting big classes into separate files first. (I know your comment is very old) Apr 23, 2014 at 14:37
26

As you say, it is often used to separate generated code. It is often nothing to do with the size of classes/files.

The benefit of separating generated code is one of style. Generated code can be pretty ugly and unreadable and would fail many coding standards (and StyleCop checks), but that's OK, no one has to read it or maintain it directly. So, if you "hide" it in another file you can focus on making sure the rest of the class is up to standard, passes StyleCop checks and so on.

Another area where I've used it is where a class implements multiple interfaces, it can be quite nice to separate the implementation in to separate files, although this is more a matter of personal preference, I've never seen any coding standards require (or prevent) this.

2
  • 10
    I'd never thought of using class partials for separating interface implementations, that's an excellent idea.
    – Mark Booth
    Apr 26, 2011 at 20:15
  • It's about much more than style. A code generator's developers would have to jump through hoops to allow you to edit code in a file managed by the generator, and even then it would be problematic. The #1 benefit, to me, is giving you a place to write code that the generator will/can not touch. This is a pretty tangible benefit.
    – Daniel
    Dec 17, 2018 at 14:25
23

I can think of a few useful scenarios where partials make sense, most of them I am using myself in my projects:

  • To separate Tool/IDE/Designer generated code from the code you are maintaining. A good example is the Form.Designer.cs file that contains the designer generated code for windows forms applications. Many other .NET formats also have some tool generated code, which can be potentially regenerated when you build your project, and thus all your custom changes will be swiped out. The separation will help you keep your code and changes safe from such automated modifications.

  • When you are implementing multiple interfaces with a lot of code in the implementation. I tend to use a separate partial file for each such interface, naming it like this: {Class}.{Interface}.cs. It is easy for me to see in the IDE which interfaces the {Class} is implementing and how.

  • When the class must contain one or more nested classes, especially with enough code in them to be put into a separate file. I would stick to the above pattern and use the {Class}.{NestedClass}.cs naming convention for each nested class. Similar practice is already mentioned by Virtlink's answer.

  • When I write static classes which will hold extension methods. It will often be the case to provide the same extension method logic to similar classes or interfaces - like for instance Reverse on generic and non-generic collections. I would put all the extension methods for a single class or interface in a separate partial of the static class. For instance, I'd have all extension methods for the IList interface in one place, and the same methods that are for IList<T> in another file. Another approach would be to put the same method (all of its overloads) in the same partial, with all possible classes for the this parameter - like having all the Reverse implementations in one file. It depends which one would better justify the separation in terms of code volume, or some internal conventions you or your organization might be sticking to.

  • I do not use this, but I've seen some C/C++ folks to like the approach I will describe here: create a partial for the class with partial methods only. This resembles the C/C++ way to define interfaces and separate the method declaration from the implementation.

  • Separation by purely logical concerns. If you happen to work with a large class that combines more than one logical set of operations in itself, then you could separate each logically-related code into a separate partial. Usually existence of such classes is against the separation of concerns principle, but it is oftenly observed real-life case, especially for older codebases. Fellow user Steve Evers has mentioned them in his answer to this question, referring to them by the name god objects. I'd personally use the approach of partial classes to split the code before any refactoring of such really large files takes place, in order to ease my work and make the refactoring more transparent. This will also reduce the conflicts I will potentially cause when versioning systems like SVN are involved.

19

One of the developers where I work came up for a pretty good use for them a couple of weeks ago in the refactoring of huge God classes that have spiralled out of control and have lots of public methods: by separating the logical functions of each bit of the class into a separate partial classes you can physically separate the class into the more atomic units that should be the classes without breaking any existing functionality, allowing you to see what is common and what is not. With this as a first stage you can then more easily break the partials out into their own independent classes and implement them throughout the code base. I thought this was a nice idea.

However, in general I think that they should only be used to augment machine generated classes when writing new code.

2
  • 1
    I can see how that could be handy. Whether that is justification for it to be in the language or not...I don't know. Machine generated code's another story, though.
    – Michael K
    Apr 26, 2011 at 19:57
  • 2
    Yes, it's not a justification for it to be in the language, but it's an interesting way to use them.
    – user23157
    Apr 26, 2011 at 20:53
18

I've not seen it mentioned by anyone: I use partial to put nested classes in their own files.

All my code files contain only one class, struct, interface or enum. It makes it a lot easier to find the definition for an object when the file names show the name of the thing you're looking for. And since Visual Studio tries to match the project folders to the namespaces, the filenames should match the classes.

This also means that a class NestedClass nested inside MyClass will have it's own file in my projects: MyClass.NestedClass.cs.

partial class MyClass
{
    private class NestedClass
    {
        // ...
    }
}
2
  • 1
    I wonder why one would down-vote this answer. The mentioned practice is neither an anti-pattern, nor it would cause any issues I know of. Apr 1, 2014 at 12:25
  • 1
    This also addresses the problem of keeping class files small (in terms of lines of code) while still allowing proper encapsulation of code that belongs in an inner class.
    – redcalx
    Jan 20, 2016 at 10:36
10

With the exception of using generated code, I have only ever seen them used in an effort to cover up for god objects. Trying to understand a new codebase or navigate through multiple source files, that are the same object, is soooo annoying.

So when you ask Why use partial classes? I answer: unless you're using generated code, don't.

1
  • +1. It is the first time I see these types of objects being called a name (god objects) and it is even official. It is never too late to learn something new. Apr 1, 2014 at 16:13
6

Code organization is the only reason, but it goes deeper than it at first seems. If you have partial classes where parts are generated you can easily:

  • Regenerate code without having to detect manual changes in the classes you write to (so that you don't overwrite those parts).
  • Exclude the generated partial classes from test coverage, source control, metrics, etc.
  • Use generated code without forcing you to base your inheritance strategy around it (you can still inherit from other classes).
1

There are also a few places where generated / implied classes are declared partial so if the Dev needs to extend them they have full access without having to mess about inheriting and overriding all over the place. Look at the generated classes in the asp.net temp area after you run a webforms site for the first time under IIS if you want to try to catch some examples.

1

I can think of a dirty use for them.

Suppose you have some classes who need common functionality, but you don't want to inject that functionality into the inheritance chain above them. Or, you have a set of classes that use a common helper class.

Basically you want to do multiple inheritance but C# no likey. So what you do is use partial to create what is essentially an #include in C/C++;

Put all the functionality into a class, or use the helper class. Then copy the helper X times and rename it partial class A,B,C. and put partial on your A, B, C classes.

Disclaimer: Yes, this is evil. Don't ever do it - especially if it will make other people mad at you.

2
  • Mixins. This could be combined with T4 to avoid manual copying... Feb 6, 2013 at 20:56
  • As noted, this closely resembles mixins. However, you're approaching a concept known as "traits" and they'll safely handle what you're trying to achieve. I have a language-agnostic description at publius-ovidius.livejournal.com/314737.html I've looked for a clean implementation for C#, but haven't seen one.
    – Ovid
    Dec 4, 2014 at 7:58

Not the answer you're looking for? Browse other questions tagged or ask your own question.