More on Partial Methods


Thank you everyone for the feedback.  If you have any more to say then please do express your opinion (and yes it is valued ;).  I think there has been a bit of misunderstanding about what partial methods really are.  So let’s set the matter straight.  Here is the current spec (quoting from here on out):

Partial methods are a new feature complementing partial classes with the option of declaring “hook” – or compile time events – in the code.

Here is an example

partial class Customer

{

  public string Name {

    get { … }

    set {

      OnNameChanging(value);

      _name = value;

      OnNameChanged();

    }

  }

  partial void OnNameChanging(string value);

  partial void onNameChanged();

}

Partial methods are only allowed in partial types; either classes or structs. There are no other kinds of partial members.

There are two parts of a partial method; the defining and the implementing partial method declaration. There can be at most one defining declaration, and at most one implementing declaration, and the implementing declaration is only allowed if there is a defining declaration. The defining declaration is distinguished by having a “;” instead of a method body. The two can both appear in the same partial type declaration.

Partial methods must always return void. The contextual keyword partial has to appear right before void – that is how we recognize it. They can have ref but not out parameters; both params and this modifiers are allowed in the usual positions.

Access modifiers on partial methods are not allowed, but partial instead implies private. The only modifiers allowed on a partial method declaration (apart from partial) are unsafe and static. Thus a partial method declaration cannot declare or override a virtual method. Also, partial methods cannot be extern, because the presence of the body determines whether they are defining or implementing.

If both a defining and an implementing partial method declaration are given, all modifiers on parameters and the method declarations themselves must be given in both declarations, although not necessarily in the same order.

Partial methods can be generic. Constraints are placed on the defining partial method declaration, and must be repeated on the implementing one. Parameter and type parameter names do not have to be the same in the implementing declaration and the defining one.

Whether or not there is an implementing declaration, a partial method participates in overload resolution and type checking in the normal way. If there is no implementing declaration, however, the method will be removed. Furthermore calls to the method are removed, including evaluation of arguments to the call, in a manner similar to conditional methods.

You can only make a delegate to a partial method if there is an implementing declaration; otherwise a compile time error occurs. Similarly, calls to a partial method occurring within the body of a lambda which is converted to an expression tree are only allowed if there is an implementing declaration of the partial method.

Because partial methods are always private, they cannot implement interface methods, neither implicitly or explicitly.

If both a defining and an implementing partial method declaration are given, attributes on the resulting method and its return type, parameters and type parameters are determined by assembling, in unspecified order, the attributes from both the defining and implementing declarations. Duplicates are not removed. Thus, for attributes that can only occur once on a given declaration, having that attribute on both declarations will result in a compile time error.

Definite assignment is only checked after the possible removal of partial method calls and evaluation of the argument expressions. Thus, if assignments occur within these argument expressions, and the method is removed, they will not affect definite assignment. This can potentially lead to compile time errors.

The Main method of a program can be a partial method, but will only be considered as the entry point for the program if there is an implementing declaration.

XML doc comments are allowed on both defining and implementing partial method declarations, but only the ones that appear on the implementing declaration will be used by the compiler. Other tools may make use of the comments on defining declarations.


Comments (16)

  1. Ben says:

    There is a typo (presumably) in the spec. One of the partial method definitions is defined as onNameChanged(). However, the method referenced is OnNameChanged(). Notice the difference in casing.

  2. Vijay Santhanam says:

    I’m trying to think about why I care about partial methods, but I can’t seem to think of any cool things you do with them other than compile time defined event handling.

    But for us average Joe Csharpys, extension methods are way cooler.

    Btw, love reading your blog. You’ve got me interested in functional languages again since university. Can’t wait to read about more cool features.

  3. R. Henry says:

    What are the practical uses for partial methods?

  4. Adam says:

    The easiest practical use is for code generation (same as partial classes). Think of a generated method that can have optional pre- and post-conditions.

    I use a code generation tool and add the CS files into my project, but now I need to perform pre- and post-condition checking in certain methods (throw exceptions and what-not, or perhaps perform additional operations the code generator hadn’t thought of). Without the partial methods I’m stuck with subclassing the generated code, hoping its method is virtual, overriding and adding my pre- and post- conditions myself.

  5. Wolf Logan says:

    While I have no strong opinions on partial methods themselves, I have a *very* strong opinion on the IDE: callsites to partial methods *must* indicate whether the partial has an implementation. Otherwise debugging is going to be nightmarish.

    A large amount of debugging is in code maintenance, when you’re dropped in front of a large body of code you’ve never seen before. If I see a method call while I’m tracing, particularly if parameters to that call are expressions with side effects, then I absolutely have to know whether that call is actually compiled into the code. This isn’t a "nice to have", for me it’s a deal-breaker whether I deal with partials at all.

    Currently, the only other situation where source code might not actually be compiled is an #if conditional block, and those blocks are properly marked in the IDE (grey if they’re not compiled). To add a feature to the compiler that can potentially ignore lines of code without telling me is a big deal.

  6. wesdyer says:

    Ben:

    Thanks for noticing.

    Vijay & Henry:

    Adam is spot on.

    Wolf:

    Very good point.  I have already given a similar opinion to the IDE team, but you should note that you have missed at least one other case where code appears in the source that doesn’t actually exist in IL: conditional methods.

    [Conditional("FOO")]

    public void M(int i)

    {

    // code here

    }

    // later on in some other code

    int i = 3;

    M(i = 5); // M and the evaluation of the arguments to call may or may not be there

             // it all depends on whether FOO is defined

  7. Wolf Logan says:

    Oof. You’re right, of course. The added complication with ConditionalAttribute is that the conditional is evaluated *at the call site*, while the [Conditional()] is applied *at the definition site*. In other words, the ConditionalAttribute acts like #if applied around the call.

    And the IDE isn’t currently marking those call sites. Oy.

    I don’t question that these are useful language features. But they remind me (uncomfortably) of chasing down declarations and definitions in dozens of C++ header files, and unravelling arcane preprocessor macros just to determine what a particular call *calls*, if indeed anything at all. I had hoped we’d moved beyond that kind of pointless bookkeeping with C#.

  8. Alejandro Argueta says:

    I can not wait to use them. Im building a model generator and they solve a huge problem for me.

  9. Tom Kirby-Green says:

    Thanks for clearing that up Wes – that makes more sense now. To me it feels a bit like lambdas and LINQ are taking C# 3 off in a new functional / declarative direction whereas partial methods are something a return to C# 1.0’s "component orientated" language roots.

  10. dpirs says:

    OK, I’ve got it. Microsoft likes the partial methods, the community needs some time to get used  on them.

    Can you now please go back and write a few great blogs about functional programming and similar stuff again? 🙂 Thanks.

  11. Tanveer Badar says:

    But why require a void return type.

    Only because this will be illegal?

    static partial class Demo

    {

      // Suppose it is allowed for a moment

      static partial int Reflexive( int i );

      static void func( int i )

      {

      }

      public static void Main( )

      {

         func( Reflexive( 5 ) ); // No definition for Reflexive, a compile time error.

      }

    }

  12. Fduch says:

    Can you write a little about dynamic typing and why we cannot use constucts such as:

    List<typeof(y)> x;

  13. I have spoken to quite a few customers about LINQ &amp; LINQ to SQL over the last few months. Oddly enough,

  14. I have spoken to quite a few customers about LINQ &amp; LINQ to SQL over the last few months. Oddly enough

  15. jakelite says:

    So for those of you aching to try the new partial methods feature this is your chance. You can access

  16. Wriju's BLOG says:

    C# 2.0 and Partial class, in one of the amazing features to work with one class separated in multiple