views:

953

answers:

8

I have been using the partial class modifier for some time in order to put helper classes in their own file.

Today we got a new guy and he said that the last team he worked with didn't allow partial classes for this because modifying a helper class that is in a separate file would cause the main partial class file to get out of whack with the changes. Also, they were only allowed to put a helper classes inside of the main class as the last resort so that everything remained decoupled.

What do you think? Is there any problem using partial classes like this or does it boil down to preference?

For instance, I usually have something like this:

  • MainClass.cs
  • MainClass.Helper1.cs
  • MainClass.Helper2.cs

...

// Inside of MainClass.cs I have code like this:

public abstract partial class MainClass
{
    // ...
}

// Then in the MainClass.Helper1.cs I have:

partial class MainClass
{
   private class Helper1
   {
       // ...
   }
}
A: 

I'm not a very big fan of partial classes and don't use them myself.

The one time I do find them helpful and OK to use however is when you want to add something to the LINQ to SQL designer code, but apart from that I find if you are spreading the code out into different files just for the sake of it, it can make it very hard to read and manage.

Maybe if you have classes split into many files maybe your classes are doing to much... just a thought:)

Nathan W
I actually find it easier to manage if each class has it's own file... That way I can have the nested class open in one window and the parent class in another window and flip back and forth more easily.
wizlb
Also, see my comment on Andrew's answer below "I guess that I don't see what size has to do with the class being nested or not..."
wizlb
+5  A: 

Personally I can't see anything wrong with using partial classes like this, but that's just my own opinion. The only thing that might seem like "bad practice" is to name your classes "Helper1" and "Helper2" (but that might be an example only for clarification).

If you're using partial classes like this, check out the (free) addin vsCommands (for Visual Studio 2008) that makes it really easy to group files in the solution explorer (just like designer files) without editing the project file.

Patrik
Thanks, I was looking for a plugin like that. I was getting by with a Macro that I wrote to do it.
wizlb
updated link to vscommands: http://blog.mokosh.co.uk/page/vscommands.aspx
jarek
Another updated link to vsCommands: http://mokosh.co.uk/vscommands/
Chris Porter
+3  A: 

Short answer: If all of the classes are your code, you don't really need helper classes, which invalidates your need for partials.

Long answer: I'm not sure that there is anything that says your practice is explicitly wrong. From my experience, if you've got several different files that compose the entire class, you do need a good reason to do so, because:

  1. Partial classes reduce readability somewhat
  2. If your classes have multiple helper classes within them, it may be a symptom of a poor design, I don't think I've ever run into a situation where I was forced to write helper classes for classes I created.

However, I think the best reason to use partial classes is code generation, where you want to be able to re-generate a file without losing custom work.

Zachary Yates
You never need helper classes, really? It surprises me because I see so many classes in the framework itself that have helper classes like private enumerators and private lists (Dictionary..KeyCollection, Dictionary..ValueCollection etc...).
wizlb
For instance... System.Enumerable has about 30 helper classes nested inside of it. (THIRTY!!) So I guess that you'd say this is possibly a bad design?
wizlb
"re-generate a file without losing custom work" is definitely the best reason for a partial class, so convenient, so useful
ChrisHDog
Well, I don't mean that helper classes are bad design. I don't use helper classes if I own the main class. I build the "helper" functionality into the main class. I do use helper classes when I don't own the main class (such as a framework/3rd party class).
Zachary Yates
+1  A: 

I think that if the nested classes are large enough that you feel the need to split them into their own files they should probably not be nested classes. Make them internal members of the same namespace as MainClass instead.

Partial classes really only exist to support code generators and using them to break programmer written code into manageable chunks is an indicator of poor design.

See this article for a hilarious example of what not to do with partial classes.

Andrew Kennan
I guess that I don't see what size has to do with the class being nested or not. A nested class is not usable by other classes so I nest a class purely to achieve that functionality. Then I put it into it's own file regardless of it's size so I can edit the nested class separately.
wizlb
Excellent link. And it might even be cogent.
le dorfier
I usually use inner classes for simple data storage. I'm not a fan of partial classes for anything other than code generators because they reduce readability of the code - especially if someone lazily puts a MainClass method in the MainClass.Helper1.cs file.
Andrew Kennan
+4  A: 

Partial classes are primarily for code-generator usage, such as designers - but I use the approach you have cited - in particular when an object implements multiple (non-trivial) interfaces, I find it useful to break it up 1 file per interface implementation. I also commonly have a file for the static methods, which are usually different enough from instance methods to warrant separation.

Marc Gravell
+2  A: 

I've actually done the same thing. As has been stated, there is a slight readability hit on deciphering the partial classes.

Decoupling is the main reason I like this solution. A private inner class is far less coupled to everything else, because nothing else can see it or use it (although they may be talking about the potential for it to access the parent class's private data, which would usually be a bad idea).

Neil Whitaker
A: 

I think it's good to remember that your tool's default behavior is to create a low-level form of Coupling Not Cohesion; and view it skeptically, and override it unless it makes sense for some of the specific reasons listed above. But it's not good default behavior.

le dorfier
A: 

Most of times I use partial class only with code generation, so I can extend my classes' behaviors on separated classes that they need some customization and don't include in code generation.

Samnang