Microsoft added a new keyword to C# and VB for 2005 (CLR 2.0): partial
Don't use it.
partial is used to physically break up a class definition into multiple files. When the compiler sees the keyword partial it finds all the related partial files in order to compile the class. This makes it possible to split the code for a single class across multiple files. By and large, though, this is a bad idea. Let’s look at why that is.
If you find
yourself typing
"p-a-r-t-i-a-l"
Stop!
Reasons Given To Use the “partial” keyword
There are three main incentives I’ve heard for using partial, according to Microsoft and others:
- If a class is really large, break it into multiple files so more than one person can work on it at a time.
- If a class implements multiple interfaces, put the methods that implement each interface into a separate file.
- When the IDE generates code, it puts the code into a separate file so you don't see it or accidentally modify it.
Let's examine each of these reasons in detail.
1. Avoid using “partial” to break large files into many smaller files—so multiple people can work on them. This is a bad practice.
Why?
No matter how you try to group code in various partial files, you will never see the big picture for the class anymore. It’ll become brittle, easily broken. By only viewing a portion of the class, you can too easily break some assumption or dependency in the rest of the class. For example, you won’t see all the internal fields. If a field needs updating, and it’s not referenced in the portion of the class you’re editing, you’ll never even realize that you are breaking the class. People will make incompatible changes and no one will know until Humpty Dumpty is put back together again. Are your unit tests good enough to catch this?
So what's the right solution for really large files?
If you’re thinking of using partial because your class file is large, then consider it a warning sign that it's time to break the class up—not by using partial but by using object oriented design. Break your monster class into multiple classes, grouped by responsibility. That way, you can hide details inside classes, and it will be much harder for developers who work on the new smaller classes to make incompatible changes with each other. As a bonus, breaking it up will also make your code easier to read, test, and maintain.
2. Avoid using “partial” to organize your class file. Some people suggest putting the implementations of each interface into their own files. This sounds reasonable at first, but it contains a pitfall—the class implements 2 or more interfaces, but it is still one class that has its own private data (and all the assumptions that go with that). If you only read code in one file and make changes, you may not realize the side effects you introduce on other methods that are in other partial files. This is a bad practice for the same reason that it was for reason #1, large class files.
3. “partial” is ok if the compiler puts it there. This is the only safe reason to use partial. When the compiler adds partial to your class, it does so to hide the code that it generates. While there are other solutions to handling generated code, this is the one that Microsoft chose, and it works fine. You can't ever modify the generated code (well, not easily) so it's just as well that it's hidden in a separate file. Note the key phrase here: the compiler adds partial—not you.
Recommendations
- If you find yourself typing "p-a-r-t-i-a-l" — stop! Don’t do it.
- If the class you’re working on is marked partial, make sure that the other partial bits are compiler-generated. If they’re not, you should consider putting the class files back together and re-factoring the large class into smaller classes.
One final Note: in VB, since the partial keyword is optional, you can really confuse someone reading the code because they may not even realize that other code exists for this class. If you work in VB, be aware that your entire class may not be in the file you’re looking at.
For another viewpoint, see these articles: