Partial classes and initialization


Partial classes can be pretty cool because of the opportunities it gives in separating machine or designer generated code from user code. It does present a few issues, however.


One that we've been talking about recently is a scenario where you have some machine generated code that can function by itself, but sometimes your user wants to extend it. And, to extend it, the user needs to have some code run as part of the constructor.


That presents a problem. If we want the user to be able to use the class by itself, it needs to have a constructor in the generated code (assuming, of course, that the generated code needs a user-written constructor, which is true the majority of the time), but that prevents the user from writing a constructor themselves.


We talked about this from a design perspective, and explored some ways in which you could write “partial methods” - for want of a better term - in your partial classes. It is possible, but in all the schemes we came up with, you end up with weird ordering constraints (“I want the user constructor code to be inserted after the first 2 lines in the constructor but before the remaining 10 lines...”)


So, basically, those schemes were all untenable.


How can you do this? Well, the best way is to provide some designer support to add a call to a user method at the appropriate place.

Comments (19)

  1. moo says:

    Yes because we know designers generate good solid code. Take WinForms designer code and RESX files, theyre very very easy to refactor (not) and why we have a policy of NOT using the designer that generates RESX files in our projects. Its near impossible to refactor without redoing the form from scratch.

  2. Here’s a possible solution:

    Use 2 files – one for the autogenerated designer stuff ( doesn’t contain the constructor ) and the second for the user code ( which contains the constructor ).

    So, whenever creating a "partial" class, make 2 files right away. That way it’ll compile the first time through without the user having to add anything. Later on, the autogenerated file keeps getting overwritten, while the "user file" doesn’t.

    Quite a simplistic solution, but I think it covers the constructor problem alright.

  3. Johnny Hall says:

    Udi, in this scenario, what happens if the designer code has to alter the constructor code, after the user has changed it?

  4. Johnny Hall says:

    Udi, in this scenario, what happens if the designer code has to alter the constructor code, after the user has changed it?

  5. Piers7 says:

    Don’t we have this problem at with constructors at the moment anyway – just with base classes rather than partial ones?

    Seems to me that if you view the designer-generated partial class the same way you view a base class – ie the ‘extending’ (user) code runs after the ‘base’ (designer) code (designer constructor always calls stub method user init method) at least you know where you stand.

    After all, in a class designed for extension (whether partial or base), things firing off that might need actions taken prior to them fire some kind of virtual OnThing() method, right…

  6. MartinJ says:

    This could get ugly, fast. I can see a recursive, or circular, situation getting introduced without some strict rules in place.

    You don’t want any direct dependencies between the user and designer code. But, you want the user to always be the one in the driver’s seat. So, I see the use of helper functions that the designer must honor.

    If the user creates a function named OnBeforeDesignerInitialization, the designer must add a call to that function immediately after any base class constructor is called.

    Basically, the brunt of the work falls on the designer to look through user code for key methods. It then controls the actual constructor method implementation to accomodate what the user wants.

    You could also do this with attributes or compiler directives (kind of like the #pragma directive) so that the user has even more control of the actual method names.

  7. moo says:

    As if code cant be made bad enough, partial methods could end up being nasty if misused. Gives a whole new meaning to obscfucation.

    Instead of adding all these fragmentation features, why not fix the designer in the first place, its schitzophrenic. .resx files don’t refactor, the designer has a mind of its own.

    If one wants theyre code with good managability, I don’t recomment the winform designer and I definately dont recommend the use of .resx files.

  8. moo says:

    Will we see Inverse P/Invoke in later IDE builds as its supported in the framework specification as far as I know so I can make a native DLL from C#.

    Will we see static linking (.lib assemblies) of .net assemblies in future builds? While today I can just do a "link to.." in the add existing… item for a project, sometimes I would like not to include the source on a project.

    While we have P/Invoke there but not Inverse P/Invoke, I dont understnad why this is left out on the IDE when its a supported feature. Delphi .NET has it I belive in the IDE.

  9. John Morales says:

    the more i hear about parital classes, the more i think they are useless…

    it’ll just lead to crappy code: a file is a logical and useful container for code components, it’s an elegant solution… maybe it won’t be THE solution in the future, but it is the main metaphor for our current coding techniques.

  10. I hope designers let us make a choice if we want partial class code or base class code. Partial classes are fine, but I fear that they’ll be abused, and instead of being able to change SomeFunction(), we’ll have to write ReallyThisIsSomeFunctionDontCallSomeFunction() if the designer functionality isn’t what we want exposed.

  11. Jim Lyon says:

    There’s an easy quick hack to get partial constructors:

    In one of the files, add a member variable declaration like "int dummy = MyPartialInitialization();"

    The compiler will stock a call to MyPartialInitialization into the beginning of whatever constructors are eventually defined (and store the result into dummy).

  12. The main use of partial classes as I see it is for code generation purposes.

  13. moo says:

    Its a good thing to have partial types if its managed well but partial methods = BAD and I will never support this. It will be removed from all code I see this in and anybody adding partial methods will get a nice talking to.

  14. moo says:

    Unions in C#



    [StructLayout(LayoutKind.Explicit)]

    public struct MyUnionWithCategories

    {

    [FieldOffset(0)] public int Category;

    [FieldOffset(0)] public char CategoryRep;

    [FieldOffset(0)] public long CategoryIndicator;

    }

    Instead of hacks like this, why cant we have a union type in C#?

  15. Eric says:

    Moo, if you have other questions, please put them in the "things Eric should blog about" thread on the main web page

  16. Nick says:

    Always funny to read about problems you wouldn’t have if you’d use a dynamic language like Python, Smalltalk, Ruby oder Lisp. If you need code generators it’s very likely something is broken at a language level…

  17. moo says:

    Ive seen developers that cry because they cant use a designer and if the designer doesnt work they refuse to touch code. WTF. Fire them. Theyre useless.

Skip to main content