Geeks With Blogs
Dave Chestnutt: SparklingCode and CodeGaffes Writing better code; for fun and profit

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:

  1. If a class is really large, break it into multiple files so more than one person can work on it at a time.
  2. If a class implements multiple interfaces, put the methods that implement each interface into a separate file.
  3. 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:

Posted on Wednesday, April 5, 2006 6:34 PM CodeGaffes , Visual Studio Tips | Back to top


Comments on this post: CodeGaffe: Avoid .NET “partial” classes in C# and VB

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB
Requesting Gravatar...
We have written an objectmodel for use with accessing a database within code, and one of the features is that there is an inbuilt class generator that will automatically generate clases based on the details of a database table, view or even a stored procedure.

However this automatically generated class i just the starting point for write code. The programmer will need to add database releated code to the class in a special "Support Methods" Region. This specific related code would normally be processing the stored procedures that make up the individual methods that relate specifically to the class in question.

As the class builder can be run at any time, the easiest and best way to protect the support methods added after the classbuilder has been run for the first time is tio add them in a partial class.

This way the generator can happily regenerate the main class time and time again (which should never be changed by the programmers) without affecting the class specific code.

I take on board everything you have written -and agree that in theory partial classes should be avoided, but that isn't to say there can be some good reasons to have them.
Left by Simon Shaw on Apr 24, 2006 4:00 AM

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB
Requesting Gravatar...
You bring up a very good point - one that's worth elaborating on.

I said you shouldn't use partial yourself, but it was ok if the compiler did. A more complete statement should say that it's ok if a tool uses partial to keep its generated code separate from your code.

So in your case, using a code generator (to create database access classes) fits into that category the same way the compiler does. Partial is used to keep the generated code separate from hand-written code.

It's a good usage of partial, but remember - there's no safe usage of partial.

Anyone who's writing a tool that generates code should think twice about using partial classes as a way to keep their generated code separate. You should seriously consider an alternative: generate code into its own class, and let your users derive from that class to implement their "Support Methods". That frees your code generator up so it can implement its stuff however it wants. Only protected & public methods need to be preserved in future versions. The alternative, using partial classes, means you have to preserve your internal private data for the future too. By letting your users "into" your class, they may write code that depends on your private fields. That's why partial is unsafe. Or at the very least - it locks more of your design in place than might be desirable.

I realize that's not always practical to use a base class for your generated code - some applications are just not worth it. But my suggestion to those who write code generators is this: avoid using partial simply because it solves the re-generation problem. Be sure you really understand that partial brings its own set of issues.

Don't let the cure be worse than the disease.
Left by Dave Chestnutt on Apr 24, 2006 10:04 AM

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB
Requesting Gravatar...
Using partial classes is fine. If you can't use the tools in VS 2005, you may not be able to see the "big picture" but hopefully you know your tools. Use the Class Explorer and group files together with the DependsUpon tag in the project file and you'll be fine.
Left by George on Dec 02, 2006 8:40 AM

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB
Requesting Gravatar...
I fully support George in that the Class Explorer is really the tool that should be used to analyze the big picture of your class structures. Partial classes can get especially hairy when trying to override base methods in complex inheritance hierarchies.

Also, the .net compilers do not generate code - it's Visual Studio that does that. I think you realize that though and I am just nerdily nit picking.
Left by Keenan Chadwick on Jan 09, 2007 8:57 AM

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB
Requesting Gravatar...
I agree that Class Explorer is a good tool, and it really helps if you've got a class that's been sprinkled across several files.

My original point, however, remains - namely that you shouldn't be breaking your classes into multiple files on your own. Don't make it difficult on yourself and others. Coding is hard enough to get right already!

...and yes: it's Visual Studio that generates code, not the compiler. Consider it a typo :)
Left by Dave Chestnutt on Jan 10, 2007 1:31 PM

# Avoid .NET “partial” classes in C# and VB
Requesting Gravatar...
Microsoft added a new keyword to C# and VB for 2005 (CLR 2.0): partial Don't use it. partial is used
Left by Bander ALSHARFI on Feb 24, 2007 11:52 AM

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB
Requesting Gravatar...
Is there a way to "turn off" partial classes when adding a new form to a VS2003 web site that has been upgraded to a VS2005 web application?
Left by Frank C. on Apr 25, 2007 4:12 PM

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB
Requesting Gravatar...
I don't know of a way to turn off partial class generation by the IDE.
Left by Dave Chestnutt on Apr 30, 2007 8:44 AM

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB
Requesting Gravatar...
The use of the "partial class" idea totally breaks the object model.
You must, more simple, write wrapping classes or derive from other.
This is the right object model.

The worst is that you CANNOT work without partial classes in VS2005 that must need to do it.

So, this is the Microsoft way?
Left by Aldo Prinzi on Jan 18, 2008 3:19 AM

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB
Requesting Gravatar...
Can we create Objects for Partial Classes. Verify this....
Left by Nagendra on Apr 14, 2008 7:47 PM

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB
Requesting Gravatar...
re: Can we create Objects for Partial Classes.

Of course. Partial is simply a way to split up your class definition across files. Not recommended that you use it explicitly.
Left by Dave Chestnutt on Apr 15, 2008 1:16 PM

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB
Requesting Gravatar...
I agree with the author's points. However, if you're in a RAD environment with very small teams, it is many times not possible to use the ideal OOP practices. A loose analogy is keeping A database highly normalized. In some situations, it's not practical, as it can slow things down, and can induce design overhead and query complexity. I've seen both areas first hand; people "over-design" short-life and low-budget projects, instead of concentrating on pumping it out and moving on to the next money project. Any of you know what I mean? Your associates are still working on their first few pages/forms while you're on 5th project and your 50th form in a month, and have have the reports written too!

Now, as a good example for the partial classes, you know that good old tab control? It's great for creating complex dialogs, like for configurations and such, right? Keeps the visual/functional interface partitioned and reduces form count. Well, anyone who's actually done complex tabbed forms, and more recently, tabbed web pages, knows that you pay for this on the backside code. You have a single form class containing say, 10 different tab pages, with private variables for each tab, all the events, etc. Taking the time to split out each tab into a self contained class can lead to over-design, over-budget and less production. Using regions is a good way to keep down the eye/scroll sores, but with complex multi-tab forms, even contracted regions can stretch for several pages. Partial classes with a separate file for each form tab can help.

And before anyone flames me about this, realize I'm talking about RAD development, where you're required to produce on a dime and over-thinking and over-OOP'ing will cost you the work.
Left by Kozmik on Jan 16, 2009 9:51 AM

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB
Requesting Gravatar...
If you are interesting in learning about avoiding side-effects in multithreaded real-life code, you can read "C# 2008 and 2005 threaded programming", by Hillar, Packt Publishing. Great book.
http://www.packtpub.com/beginners-guide-for-C-sharp-2008-and-2005-threaded-programming
Left by Erik Guerrero on Feb 11, 2009 6:24 AM

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB
Requesting Gravatar...
I know this article was written a long time ago, but what utter rubbish!

Partial classes are not Evil. Of course, you can do evil things with them, but you can do lots of other stupid things anyway.

It's all about HOW you use partial classes.

Using them to allow more than one developer to work on the same class at the same time is probably not wise.

However, using partial methods to provide easy extension points to existing classes is a really fast, intuitive and efficient way to do it.

I don't think you've given a balanced argument in your article. It's very biased.
Left by A Real Programmer on Jun 14, 2011 8:14 AM

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB
Requesting Gravatar...
Fully agree. If you feel you would need to use partial classes usually means you have your classes structure wrong and should review your project architecture.
Left by Ed on Oct 27, 2011 10:14 PM

Your comment:
 (will show your gravatar)


Copyright © Dave Chestnutt | Powered by: GeeksWithBlogs.net