Udostępnij za pośrednictwem


Partial Methods

Partial methods are a C# 3.0 technique used by code generators such as the one found in the LINQ to SQL Designer. They help to solve the age-old problem of allowing users to modify auto-generated code without fearing that their changes will be overwritten if the code is regenerated.

NOTE: The LINQ to SQL Designer is covered here.

When combined with partial classes, partial methods allow the developers of auto-generated code to reserve a name for a method that can be optionally implemented by the consumer of the class. This gives a developer a place where she can optionally add code that will never be overwritten if the code generation tool is re-run.

Listing 1: A simple example of a partial method

 using System;

namespace PartialMethods
{
    // Assume this class is autogenerated
    public partial class MyPartialClass
    {
        partial void MyPartialMethod();

        public void CallPartialMethod()
        {
            MyPartialMethod();
        }
    }

    // Assume this class is written by hand
    public partial class MyPartialClass
    {
        partial void MyPartialMethod()
        {
            Console.WriteLine("Second half");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyPartialClass p = new MyPartialClass();
            p.CallPartialMethod();
        }
    }
}

Consider the code shown in Listing 1. Assume that the first instance of MyPartialClass was auto-generated by a visual designer that is part of Visual Studio. Notice that the class is declared as partial, as is MyPartialMethod. Notice that MyPartialMethod contains a header, but no implementation. You can consider this an invitation to the developer to implement this method if desired.

Assume that the developer took up the invitation and created by hand the second half of MyPartialClass. In this class she has written her implementation for MyPartialMethod, which will duly be called at runtime by the code in the first part of this partial class. If she had decided to decline the invitation, then the code to call MyPartialMethod would have been optimized out by the compiler, causing all traces of MyPartialMethod to be entirely eliminated at run time.

This system allows the developer to re-run the designer that created the first part of MyPartialClass without fear that this action would overwrite the code in her half of MyPartialClass. It also allows the developer to work with a relatively small implementation of MyPartialClass that contains only a few methods, without needing to wrestle with the potentially long and complex listings that are often found in auto-generated code.

The rules governing partial methods state that they:

  1. Must be declared inside a partial class.
  2. Must contain the keyword partial followed by the keyword void.
  3. Cannot be marked as extern
  4. Can be marked static or unsafe
  5. Can be generic
  6. Can have ref parameters, but not out parameters
  7. Cannot be referenced as a delegate until they are implemented
  8. Cannot have access modifiers such as public, private or internal. Partial methods are implicitly marked as private. This means they cannot be called from outside the partial class, and cannot be declared as virtual.

Since they are primarily designed as a tool for use with auto-generated code, it is unlikely that most developers will ever design and write both halves of a partial method. However, the SQL Designer does make heavy use of partial methods, so many LINQ developers will want to understand this technology.

kick it on DotNetKicks.com

Comments

  • Anonymous
    November 11, 2007
    PingBack from http://msdnrss.thecoderblogs.com/2007/11/11/partial-methods/

  • Anonymous
    November 11, 2007
    Good stuff .. very excited about partial methods :) In my opinion, the power of them in C# is that when not implementing a body of a method, it will not be compiled into the output assembly. If you look at the IL level, you'll see that the methods and method calls will be removed...

  • Anonymous
    December 10, 2007
    In an earlier post I showed how LINQ developers can connect to a database and write a simple query. This

  • Anonymous
    December 11, 2007
    I may be missing the point a bit (I hope so), but how does this differ significantly from abstract methods (other than not being compiled into the assembly when not required)?

  • Anonymous
    December 11, 2007
    Looking forward to partial methods being used in the SubSonic O/R generated code. Will save me a lot of headaches. This is a really useful feature unlike a few others which may be mildly termed as retrogressive - Lambda expressions for one comes to mind.

  • Anonymous
    December 11, 2007
    @Darren, this features comes in really handy when you want to modify code that has been generated for you - say when you are using code generated by an O/R mapper. When the db schema changes and you have to regenerate code, your changes are overwritten. Some code-generators use unsightly artifacts within comments to preserve user modified code. Goes without saying that the user must not go anywhere near those comment-markers. Partial methods offer a more robust and elegant solution.

  • Anonymous
    December 12, 2007
    The comment has been removed

  • Anonymous
    December 15, 2007
    Though you'd have to inherit, virtual methods would work just as well, right, and with fewer limitations? Guess I miss the point, doesn't seem worth the effort to add this.

  • Anonymous
    December 15, 2007
    The comment has been removed

  • Anonymous
    December 16, 2007
    Charles: "Though you'd have to inherit, virtual methods would work just as well, right, and with fewer limitations?" I implemented few years ago code-generation framework for ORM in C# 1.1 and using this virtual method approach. So instead of partial classes I used classes with virtual methods and derived other classes of those that implemented (by hand-coding) some of those methods. While this works, there was significant down-side to the present partial method possibility: Instead of one class (say "Person") that is defined in two parts I had to have TWO classes (say "Person_BASE" and "Person"). This becomes messy when the generated code has to create instances of classes: The generated code (Person_BASE) has to create then istances of Person creating ugly two-way dependencies between the classes. But it does work.

  • Anonymous
    December 18, 2007
    Is this available in VB, if not, any plans to add it? We generate code in both languages, this would solve a big problem for us if it was available in VB also.

  • Anonymous
    December 19, 2007
    This is standard GoF template pattern or strategy pattern. The way to use partial method to implement this is kind of strange. It can be easily implemented as abstract class, base class with override. Or simplely a class allow inheritance with capability to override - which has been well known in the industry.

  • Anonymous
    December 20, 2007
    Is there a way to control the order in which the partial methods get their code executed?

  • Anonymous
    December 21, 2007
    Hi, Everything sounds nice, (you can modify generated code behaviour, blabla), but... ONLY when this generated code is so kind, that it bothers to call your partial method at all (e.g. there is no use for partial methods if code generator does not generate a call to the partial method). Am I right? Looks quite messy and highly unpredictable to me, without knowing generated code inside out - e.g. when actually is partial method called (but then we are missing the point of generating it...) I would still preffer a good design instead ;)  (a base class with abstract/virtual methods, and partial classes for generated descendants. For me it is just lovely, and enough (as for my 15 years industry experience)). But it may be very handy though, (e.g. when changing already bad design is not an option, but slight modification to custom code generator is). cheers

  • Anonymous
    December 27, 2007
    The comment has been removed

  • Anonymous
    December 27, 2007
    bushi, the abstract/inherited strategy doesn't have any advantages over the partial strategy in the areas you're concerned about. There's no way to know (without, like you said, knowing the generated code intimately) when, or even if, the abstract method will be called. The fact that the generated code -has- a partial method is a pretty good indication that the method will be called, and the documentation (you do have documentation, right?) should describe when and how the method will be called. The exact same situation that you'd have with an abstract class, but much less complicated, and much more efficient.

  • Anonymous
    December 27, 2007
    I can see the value in this I suppose - you get the speed of being compiled into a single function ultimately (as opposed to a vtable virtual call) and have the choice of not implementing if desired. It's very reminicent of the split between C++ headers and implementation files.  You'd have the code generator spit out the header and one implementation file, with the partial methods declared as inline and implemented in a hand coded file.

  • Anonymous
    December 30, 2007
    I took a look at VS2008 and the intellisense does help with providing the (actual) implementation of the partial (latent) method.  Like typing "override", which results in the list of virtual methods popping up, the list of partial methods popped up when you typed "partial".  An implemented member disappears the next time you typed "partial". Not having VS2008 would likely mean more work.

  • Anonymous
    January 01, 2008
    re: Ken: I'd guess the compiler wouldn't let you do that. I haven't  tried it, but it'd be pretty silly. What if you provided two implementations of an overridden method in two halves of a partial class? Or two regular methods, for that matter? re: Paul: The lack of intellisense wouldn't be any worse for the partial method than it would be for the abstract/virtual method, right?

  • Anonymous
    January 01, 2008
    At first I was surprised to see this option, since partially classes would be just fine in code-generation, in combination with abstracts. But if you look at the restrictions of usage, you can only use private voids. So it might be useful in cases where inheritance would be over-the-top.

  • Anonymous
    January 02, 2008
    This reminds me of the template method pattern which confused me at first.  Now that I've thought about it I can see how this works.  The template method pattern's goal is to define the steps of an algorithm while leaving the implementation of those steps to the inheriting class.  It's a good method for leaving a system closed for modification but open for extension.  With partial methods the goal isn't to leave the system open for extension but instead to make it easy to use auto generated code.  The code generating tool will produce the code that defines the steps that make up an algorithm but it is up to the developer to provide the implementation of some/all of the steps.  This can be done in a separate source file and written once without having to worry about it being overwritten.  Also, in contrast to the template method pattern, an artificial inheritance hierarchy is not introduced into the model.

  • Anonymous
    January 17, 2008
    Partial methods? Whatever. You know, sometimes terminology equals significant perspective shift such that it can count as innovation. I am not sure this is it. In fact, it more resembles confusion. There seems to be an aversion to OOA/M/D/P (Ojbect Oriented Modeling, Analysis, Design, Programming) techniques, although .Net itself is a good OOE (OO Environment) minus multiple inheritance, overuse of sealed, underuse of virtual, and underuse of Interfaces. Ah well. Maybe there is a really good reason.

  • Anonymous
    January 22, 2008
    @mark: "the abstract/inherited strategy doesn't have any advantages over the partial strategy in the areas (...)". I think it has some important advantage: When implementing virtual method YOU decide WHEN and IF you will call base method. So you have much greater controll on the actual code flow, and you DON'T necessary have to know anything about the base, since you can rewrite method completely, or prepare some object data before base class call, etc. This is what OOP is all about - descendants know better what's good for them, than base classes. "The fact that the generated code -has- a partial method is a pretty good indication that the method will be called". I will answer the same: The fact that the method is declared virtual is a pretty good indication that the method will be called. Equally good, or equally bad indicator. "and the documentation (...)" yeah, sure ;). Still, I agree that this approach ("having something like virtuals without inheritance") may be sometimes usefull, but I still prefer OO techniques, as it enforces thoughtfull design. cheers

  • Anonymous
    January 24, 2008
    I do see some limited value for this feature in certain areas, and obviously it was designed specifically with code generation in mind. But it seems to me that spending time adding a fairly complex feature to address a corner case was a waste, especially given all of the other features that developers have been begging for that are still missing. I wish the C# language team would spend more time addressing developer concerns and less time playing with pet features.

  • Anonymous
    January 25, 2008
    I think it a little similar with event delegation except the implementation of an event has to be in a program invoking the target class.  right?

  • Anonymous
    January 25, 2008
    @Edward, Not really, no. What you are describing is a kind of inversion of control. That is not what is happening here. Partial methods are simply a way of declaring that a method MIGHT exist without actually supplying the implementation for that method. The implementation, if any, must still be supplied within another partial declaration of the same class. If there is no implementation at the point when the class is compiled, the method simply disappears.

  • Anonymous
    March 24, 2008
    I think we need to understand the partial method's usefulness in context of partial classes. I think its a very useful feature for partial class development, specially classes that have complex logic specifically logic that involves series of steps. As each of these steps could be declared as partial methods and these partial methods are developed in separate partial classes. The original partial class doesn't have to wait for the other classes to complete before putting its logic together. public partial class MyClass {       partial void method1();       partial void method2();       public void MyMethod()       {           method1();           method2();       } } public partial class MyClass {     partial void method1()     {       //method1 implementation is now avaliable      } } public partial class MyClass {     partial void method2()     {       //method2 implementation is now avaliable      } }

  • Anonymous
    April 22, 2008
    Maybe they should have just added the keyword 'protoype'.

  • Anonymous
    July 25, 2008
    What will be done if two developers give the implementation of partial method in their own partial classes?