I’m working with a fairly large codebase – a few of my base classes have several thousand lines of code. Not huge, but certainly unwieldy when you need to be hopping around the codebase. There’s just no great way to organize everything. While some folks eschew regions, I find them useful when used sparingly and what I’ll call “correctly”. In other words, regions never go inside a method, that can quickly lead to a mess; but they’re useful to group a bunch of related members and be able to quickly hide them. In some cases, those members can and should be moved to a separate class, and in those cases that’s what I do. But in some cases, a separate class doesn’t make sense. Regions do.
But even that isn’t enough sometimes. In my current codebase, I have a bunch of interfaces which my various classes implement. Each interface defines 5-10 members, so they’re pretty tiny, but even that can get unwieldy. My core base class implements 5 of those interfaces, which means that it has something around 40 methods just to implement its interfaces – that’s not getting into some of the core logic for that abstract base class, just its interface implementations. It also has a bunch of private methods and properties which it needs to do its job. Wading through all of that code can be a headache sometimes. Worse, I’m still a little old fashioned and sometimes I want to (gasp) *print* some of my code to be able to analyze it and draw circles and arrows while working on it. Regions don’t help when printing – everything collapsed inside the region gets printed.
That’s where partial classes come in.
I’ve started breaking my larger classes into partial classes – one file for each interface. Now everything related to ISecurable or IStorable, for example, is on one place. Each code file is now closer to 7-800 lines of code instead of 3-4000. Much easier to work with.
The best part is, neither Visual Studio nor the compiler care. The compiler happily combines the separate files together into the exact same MSIL as if they had been all in one big file to begin with. Visual Studio doesn’t miss a beat, either. Not only does it have no trouble with the separate files, it still shows me proper Intellisense across files:
Furthermore, Visual Studio is smart enough to show me all of the members of my class, even those defined in another file from the one I’m currently working in, and it even shows them dimmed so I know they’re in another file:
Other Visual Studio functions, such as Peek Definition, Go to Definition, Find All References, etc., continue to work as well.
Typically partial classes are used to separate generated code from developer-written code. Other folks use them to allow multiple developers to work on the same class at the same time. This is just one more case where partial classes provide real value. I know some folks will disagree with this, and that’s fine. To each their own. To my mind, partial classes, like regions, provide significant value when used appropriately and in moderation.
One final point, I organize my partial classes a little differently than I think other folks might, and I think this helps keep things straight. Every partial class in my code base is in a folder named for the class. Each file of the partial class has the same base part of its name – the name of the class, but then it also includes the interface implemented in that file. Here’s a view of Solution Explorer showing one of my partial classes (RepositoryItem):
Each interface gets its own file, and then there’s RepositoryItem-Core, which contains everything else for the class.