Jaa


What's the difference between a partial method and a partial class?

Like "fixed" and "into", "partial" is also used in two confusingly similar-yet-different ways in C#.

The purpose of a partial class is to allow you to textually break up a class declaration into multiple parts, usually parts found in separate files. The motivation for this feature was machine-generated code that is to be extended by the user by adding to it directly. When you draw a form in the forms designer, the designer generates a class for you representing that form. You can then further customize that class by adding more code to it. If you can edit the machine-generated code then any number of problems arise. What if it is re-generated? What if the machine is using the code itself as a persisted state for design-time information about the class, and your edit messes up the machine's parser? It's much better to simply put the machine-generated half in its own file, generate a comment that says "can't touch this", and put the user code in its own location.

There are other uses of partial classes that do not involve machine-generated code but they are relatively rare. Some cases where I see partial classes used are:

  • If a class is really large and implements a bunch of interfaces, sometimes one interface implementation per file makes sense. More often though this is a bad code smell which indicates a class that is trying to do too much; it might be better to split this thing up into multiple classes.
  • It's somtimes nice to put nested classes in their own files; making the containing class partial is the only good way to do that.
  • And so on.

Partial methods are a subtly different story. Like partial classes, partial methods are about combining multiple declarations of the same method to make machine-generated code scenarios better. But though the high-level purpose of the feature is the same, the details are rather different.

The way a partial method works is there are two declarations, the "latent" declaration and the "actual" declaration. The latent declaration does not have a body, like it was an abstract method. The actual declaration does. The latent declaration goes in the machine-generated side of a partial class, the actual declaration goes in the human-authored side. If there is an actual declaration, then the latent declaration is completely ignored. But if there is no actual declaration then all calls to the method are removed, just as it the method were compiled with the conditional attribute! And in fact, the latent declaration is also logically removed when we spit out the metadata for the generated class; it's as if it never was.

The reason for this behaviour is because we wanted to enable this scenario:

// Machine generated code:
partial class MyFoo
{
void ButtonClickEventHandler(/*whatever*/)
{
// call user code to see if they want to do anything at this time
OnBeforeButtonClick(whatever);
blah blah blah
// call user code again
OnAfterButtonClick(whatever);
}
partial void OnBeforeButtonClick(/*whatever*/);
partial void OnAfterButtonClick(/*whatever*/);
...

The user is going to be customizing the partial class; by putting in partial methods, the machine-generated side can create simple customization points all over the show that the user can then implement. But consider the down sides of this in a world without partial methods. The user is forced to implement empty methods. If they do not, they get errors. There are potentially hundreds of these empty methods to implement, which is vexing. And each of those methods generates a non-trivial amount of metadata, making the final binary larger than it needs to be. Disk space is cheap but network latency has replaced disk space as the factor that discourages large assemblies. If we can eliminate that metadata burden, that would be great.

Partial methods fit the bill. The user can provide actual implementations for as many methods as they choose, and now this becomes a "pay to play" model; you get as much implementation expense as the number of actual methods you implement.

The name of the feature during the design process was "latent and actual methods"; we strongly considered adding new keywords "latent" and "actual". But since the feature only makes sense in partial class scenarios, we decided to re-use the existing contextual keyword "partial" and renamed the feature. Hopefully the consonance between the two uses of "partial" helps more than the subtle differences hurt.

SUPER EXTRA BONUS: Yet more partiality

We considered adding a third kind of "partiality" to C# 4; this feature made it through the design phase but got cut before implementation. (If there is high demand, we'll consider adding it to hypothetical future versions of C#.) 

Sometimes you're in a machine-generated code scenario like this:

// Machine generated
partial class C
{
int blah;
...

and then in the user-generated side of things, you want to do something like:

// User generated
partial class C : ISerializable
{

And oh heck, I need to put the NotSerialized attribute on blah, but I cannot edit the text of blah because when it gets re-generated, that will be lost.

The idea of this new kind of partiality is to re-state the declaration of a member -- a field, method, nested type, whatever -- with metadata attributes. It's like a latent/actual method but in reverse; the "actual" thing is in the machine-generated side, the "latent" thing in the user-generated side is just there to add metadata:

[NotSerialized] partial int blah; // not actually a declaration of a field

I like this feature but during the design process I pushed back hard on using the "partial" keyword to have a third meaning subtly different from the other two. Adding this confusion once seemed justifiable, but twice? That's pushing it. We therefore settled on adding another contextual keyword:

[NotSerialized] existing int blah; // not actually a declaration of a field

Decorating a declaration with "existing" would mean "this is not a real declaration, this is a mention of an existing declaration; please verify that such a declaration exists somewhere else in this partial class, and add this metadata to that member".

Like I said, this handy feature got cut because of resource constraints. If you have really awesome scenarios that this would make easier, I'd love to hear about them; obviously I cannot make any promises about possible future features of unannounced, entirely hypothetical products. But real user scenarios are a highly motivating factor in getting budget for features.

Comments

  • Anonymous
    September 14, 2009
    A scenario that immediately comes to mind for this feature is to stick attributes onto fields of classes generated by LINQ to SQL or Entity Framework designers. I see at least one question about how to do it on Stack Overflow every week, and so far the stock reply is "you have to forget about designer and hand-code your classes", which obviously isn't perfect. Indeed, I believe it was the entity framework team that first requested this feature of us. -- Eric

  • Anonymous
    September 14, 2009
    The last case seems as if it could be handled through existing language features. A class level NonSerialized attribute with a parameter list of which fields to skip could handle the problem without making a special language feature.

  • Anonymous
    September 14, 2009
    It's funny you mentioned partial methods. I just learned about them a couple weeks ago, and ran into a need for them last week. And now you have a whole article about them! Is there any way that you could make it so that only one part of the partial class has to name the base class? That way the code generator could always generate generic classes and the person adding implementation could decide what class to inherit from. As it is now, you have to figure out some way to tell the code generator what each class is supposed to inherit from. Or edit the generated code each time.

  • Anonymous
    September 14, 2009
    Seconding Gabe's feature request. Better yet would be to allow different base classes to be named as long as one of them is a derived class of all the others. So the generated side can say "I inherit from System.Web.Forms.UserControl" and the human-generated side can say "Actually I inherit from FooCorpCustomControl which inherits from UserControl" and the resulting class ends up deriving from FooCorpCustomControl.

  • Anonymous
    September 14, 2009
    Isn't what Gabe is asking for the existing behavior? (sample from MDSN): partial class Earth : Planet, IRotate { } partial class Earth : IRevolve { } They are equivalent to the following declarations: class Earth : Planet, IRotate, IRevolve { }

  • Anonymous
    September 14, 2009
    The comment has been removed

  • Anonymous
    September 14, 2009
    It has always been odd to me that partial methods make this distinction between the "latent" declaration and the "actual" declaration; it would have been much more natural to me to treat them just like partial classes, where any number of declarations are allowed as long as the declarations don't conflict (and obviously having more than one implementation would be a conflict). This would also have made the distinction between partial classes and partial methods less severe, and lessen the confusion around the overloading of the partial keyword. I can also imagine that it would enable some edge cases where the same class is partially generated by different generators. "Partial members" (or whatever it would be called) could work the same way: you can re-define a partial member as many times as you want as long as the definitions don't conflict.

  • Anonymous
    September 14, 2009
    oh it is a shame that the c# team has so few resources. if it took you 100 million $ to increase productivity by 10% (easy) it would be amortized for microsofts internal c# usage in one single year. it is an outrageous economic mistake. same for c++. same for the .net runtime wich could be optimized so that .net starts up as fast as c++ so it can be used to develop windows (thats easy too: just write an il -> native binary compiler and not release it to the public).

  • Anonymous
    September 14, 2009
    > Thats easy too: just write an il -> native binary compiler http://msdn.microsoft.com/en-us/library/6t9t5wcf.aspx

  • Anonymous
    September 14, 2009
    I agree with David Nelson. I understand the "partial" keyword as "there's some more about that elsewhere", so using the "partial" keyword to add attributes to generated fields seems ok to me... I would be more confused with an "existing" keyword. And you could use "partial" for pretty much everything (properties for exemple to add a "get" or a "set", abstract classes, interfaces...).

  • Anonymous
    September 14, 2009
    I don't see any value in existing keyword except to hide a minor weakness in the code generator. I think we need better code generators instead of a language feature in this particular case. After all, attributes are just metadata not code, they can be added by any code generator (for example, the class designer does it very well).

  • Anonymous
    September 14, 2009
    Yet more partiality.... Please let me know how to effectly make my "DEMAND" for the ability to use partial methods (or something equivilant) for decorating items with additional attributes have sufficient weight that it will be added ASAP.... ps: Hopefully it doesn't involve anything illegal, immoral or fattening (actually fattening would be OK!)

  • Anonymous
    September 14, 2009
    I noticed a 'creative' new use of partial classes recently.   The Bling framework is a very slick DSL-in-C#, heavily using expression trees to manage complex layout/animation/shaders in WPF applications. It uses a curious code organization with many of it's core classes marked as partial and spread across several files by area of concern.  For example, there's a Value<T> class that's spread between DSL.cs, DataBinding.cs and Physics.cs.   In many senses the code added in DataBinding is build on what's in DSL, and similarly the Physics code depends on previous two. The resulting framework is very very cool, but I'm undecided on the merits of this use of partial classes. Does anyone else write code organized this way?

  • Anonymous
    September 14, 2009
    Your sample code "should" be OnButtonClicking() and OnButtonClicked() to comply with the code analysis (FxCop) naming guidelines.

  • Anonymous
    September 14, 2009
    I believe the last feature you describe is achievable through "buddy classes"...? http://blog.pagedesigners.co.nz/archive/2009/08/06/asp.net-mvc-2-ndash-buddy-classes-for-your-models.aspx

  • Anonymous
    September 14, 2009
    Blake: I like and use this sort of code organization, but the prevailing design orthodoxy frowns on the kind of "classes" which it produces. > And in fact, the latent declaration is also logically removed when we spit out the metadata for the generated class This is logical, but I got tripped up by this tidbit while working with my macro extension for C# and had to drop the "partial method for generated code + normal method which calls the partial" idiom. Anyway, there are rather severe limitations on the signatures of partial methods — again perfectly logical, but not very convenient for general use. Ram & Pop Catalin: agree. PS: Pop Catalin, do you play Go by any chance? :)

  • Anonymous
    September 14, 2009
    @Antun Tykhyy: That would be Catalin Taranu and Pop Cristian :)

  • Anonymous
    September 14, 2009
    @ Anton TykhyyPS:  "Pop Catalin, do you play Go by any chance? :)" Well not really a favorite game of mine, but I love and do play chess. Sorry to everyone for the OT but why you ask?

  • Anonymous
    September 14, 2009
    Christian Pop and Catalin Taranu are the best Romanian Go players, both 7 dan. Goran — bull's-eye! http://www.europeangodatabase.eu/EGD/Player_Card.php?&key=10333389 http://www.europeangodatabase.eu/EGD/Player_Card.php?&key=10586785

  • Anonymous
    September 15, 2009
    Other than the disk space savings, what benefit is there to partial methods over virtual methods? Also, did anyone discuss re-tasking the virtual/override keywords for fields in the "partial field" scenario rather than  keyword? It seems to be much more conceptually related than what you've done here, and could be used more readily in an inherited design. The purpose of an inheritance relationship is to express an "is a kind of" relationship between two concepts in the domain being modelled. That you can use an inheritance relationship as a mechanism for providing extensibility points from a machine-generated class to a user-customized class does not imply that you should. Inheritance is a powerful and complex mechanism and in single-inheritance languages you only get to do it once, so you need to "spend" your use of inheritance carefully. When we designed the VSTO architecture we had a huge debate over what parts should use inheritance, what parts should use aggregation, what parts should use events, and so on. Each have their own benefits and drawbacks. -- Eric

  • Anonymous
    September 15, 2009
    I've just spent the past several days working on a code-gen system and figured I'd have to use partial classes and methods to implement some "abstract" functions, so thanks for the timely post! I'm not sure what some other people here are on about with respect to the system being useless or unwieldy - I think once you actually start working on a code gen, it's obvious how necessary and (relatively speaking) easy it is.  I just wish that there was a simpler way to get all of the code gen integrated with the IDE, without the massive overkill and inflexibility of the DSL.  All this mucking about with COM registrations and registry settings and XML schema catalogs... sigh.

  • Anonymous
    September 15, 2009
    I like Doug's idea for a class level NonSerialized attribute, but unfortunately that would only fix the NonSerialized attribute. You really need something like PostSharp, so that you can add any attribute to any machine-generated member at compile-time. (Sorry if this shows up multiple times - the MSDN blogs seem to be blocking me!)

  • Anonymous
    September 15, 2009
    Why is it necessary to use two keywords partial and existing instead of using only existing?

  • Anonymous
    September 15, 2009
    One of the big wins for partial classes and generated code is the ability to make a generated class implement a user-defined interface.  I've found this very useful with Linq2Sql and unit testing.

  • Anonymous
    September 15, 2009
    Ironically I was lamenting this feature being missing today, as it is going to add a lot of extra work for us, we would like to decorate the properties on fields returned from a WCF service with Data Validation attributes for our Silverlight app. This not being possible without completely hand coding the data objects in the service references, it's back to the drawing board.

  • Anonymous
    September 16, 2009
    I'm not in favour of having a new keyword for this purpose. The idea is an extension of partial classes, it makes sense to use the same keyword and it's not hard to understand.

  • Anonymous
    September 16, 2009
    I'm not in favour of having a new keyword for this purpose. The idea is an extension of partial classes, it makes sense to use the same keyword and it's not hard to understand.

  • Anonymous
    September 16, 2009
    The comment has been removed

  • Anonymous
    September 17, 2009
    Very cool idea with the member existing keyword. I would think that would be very helpful for things like documentation for example. Lots of code generation utilities do not put in the nessecary XML comments which results in compiler warnings for missing documentation members, currently the only way to fix that is to modify the machine generated code.

  • Anonymous
    September 27, 2009
    The comment has been removed

  • Anonymous
    September 28, 2009
    Ward, I have to disagree with you about conflicting definitions. First of all, there is no such thing as [Nonserializable]. There is [NonSerialized], but that only applies to fields, whereas [Serializable] applies to types. But even if there were two attributes whose meanings conflicted, how would the compiler know that? Attributes are never related just by definition, it is only in how they are used by implementation code that their meanings might conflict. At that point it is up to that implementation to decide how to resolve the conflict, whether one or the other attribute should win, or some kind of error action should be taken (such as throwing an exception). But the compiler has no part in that: it should merely output both attributes as requested. More generally, I think it is a very bad idea for the compiler to start mediating between conflicting definitions of any code element. If the template marked something as [NonSerialized], it is because it needs it to be [NonSerialized]. Trying to change that using another definition (which would require a special syntax to "remove" the generated attribute) will most likely break the behavior that the template was designed to enable. Allowing multiple definitions and choosing one to "win" would be a nightmare for debugging and code maintenance. I think the (hypothetical) "existing" feature (and also partial methods) should work the same way as partial classes do now: combine all the definitions, and fail if they conflict.

  • Anonymous
    November 16, 2009
    Partial classes for encapsulation: how to encapsulate a set of classes within an assembly, without using nested classes? That is, I wish to encapsulate class B so it is only accessible to A, within the assembly: "internal" doesn't work; only nesting B in A will work. A may be internal or public. Once you start writing code that way, you get large class files (quickly you notice most classes do not need to be internal). And pretty soon you wish to break up the file using partial clases. That is one use of partial classes, outside of machine generated code.

  • Anonymous
    October 08, 2012
    I´m currently using Web Service Software Factory 2010, with this feature,  implementing WS-Transactions would be a piece of cake.