Friday, December 08, 2006

Partial Classes

Microsoft .NET Framework 2.0 and Visual Studio 2005 introduce a concept called partial classes. Partial classes allow you to divide the code from a single logical class into multiple files. This can help alleviate the problem of file contention among developers. Visual Studio 2005 uses partial classes when you add a Windows Form to your solution. Instead of having to see all of the designer generated code within your class, this is hidden away in a partial class. The designer generated code for a file named FileName would be stored in a partial class named FileName.Designer.cs.

The only thing you have to do in code to make a class a partial class is to add the partial identifier as part of the class declaration. In C#, all files that make a class have to have the partial class designation. In VB.NET only one of the files that make up the class have to have the partial class designation.

After using partial classes for some time, one of my files was becoming rather large. I decided I'd try to add another partial class, FileName.SectionA.cs. It worked great but unfortunately it didn't appear in VS underneath the FileName.cs file the way FileName.Designer.cs did. This bugged me. After poking around for a while both within Visual Studio and on the web, I was unable to find a straightforward way to do this. I started looking at the project file itself and I noticed that FileName.Designer.cs looked something like this:

<compile include="FileName.Designer.cs">
<dependentupon>FileName.cs</dependentupon>
</compile>

The file that I had added looked something like this:

<compile include="FileName.SectionA.cs">
<subtype>Form</subtype>
</compile>

By editing the project file with Notepad I replaced the SubType node with the DependentUpon node like so:

<compile include="FileName.SectionA.cs">
<dependentupon>FileName.cs</dependentupon>
</compile>

After reloading the project... voila! I got the result I was looking for which was FileName.SectionA.cs appearing underneath FileName.cs.

The only downside to this approach I've found is that by default, if you checkout FileName.cs then all of the subsequent "child" files (such as FileName.Designer.cs and FileName.SectionA.cs) are also checked out. If your main concern is file contention then you need to consider this. If you're more interested in better organization then this is probably not an issue but I felt it was worth mentioning.