Dave Chestnutt: SparklingCode and CodeGaffes

Writing better code; for fun and profit

  Home  |   Contact  |   Syndication    |   Login
  17 Posts | 1 Stories | 24 Comments | 21 Trackbacks

News

Tag Cloud


Article Categories

Archives

Post Categories

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:

Technorati tags: , , , ,
posted on Wednesday, April 05, 2006 6:34 PM

Feedback

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB 4/24/2006 4:00 AM Simon Shaw
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.

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB 4/24/2006 10:04 AM Dave Chestnutt
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.


# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB 12/2/2006 8:40 AM George
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.

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB 1/9/2007 8:57 AM Keenan Chadwick
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.

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB 1/10/2007 1:31 PM Dave Chestnutt
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 :)


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

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB 4/25/2007 4:12 PM Frank C.
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?

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

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB 1/18/2008 3:19 AM Aldo Prinzi
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?

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB 4/14/2008 7:47 PM Nagendra
Can we create Objects for Partial Classes. Verify this....

# re: CodeGaffe: Avoid .NET “partial” classes in C# and VB 4/15/2008 1:16 PM Dave Chestnutt
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.

Post Feedback

Title:
Name:
Email: (never displayed)
Url:
Comments: 
Please add 5 and 4 and type the answer here: