Freigeben über


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

  • Anonymous
    May 30, 2007
    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.

  • Anonymous
    May 31, 2007
    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.

  • Anonymous
    May 31, 2007
    What are the practical uses for partial methods?

  • Anonymous
    May 31, 2007
    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.

  • Anonymous
    May 31, 2007
    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.

  • Anonymous
    May 31, 2007
    The comment has been removed

  • Anonymous
    May 31, 2007
    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#.

  • Anonymous
    May 31, 2007
    I can not wait to use them. Im building a model generator and they solve a huge problem for me.

  • Anonymous
    June 02, 2007
    The comment has been removed

  • Anonymous
    June 03, 2007
    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.

  • Anonymous
    June 04, 2007
    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.   } }

  • Anonymous
    June 11, 2007
    Can you write a little about dynamic typing and why we cannot use constucts such as: List<typeof(y)> x;

  • Anonymous
    July 12, 2007
    I have spoken to quite a few customers about LINQ &amp; LINQ to SQL over the last few months. Oddly enough,

  • Anonymous
    July 12, 2007
    I have spoken to quite a few customers about LINQ &amp; LINQ to SQL over the last few months. Oddly enough

  • Anonymous
    July 26, 2007
    So for those of you aching to try the new partial methods feature this is your chance. You can access

  • Anonymous
    December 13, 2007
    C# 2.0 and Partial class, in one of the amazing features to work with one class separated in multiple