Let us corrupt C# for code generators: The horror story of partial methods
I think you can pretty much understand how I feel about this feature.
Think about it, a compile time only method declaration, that you can "override" in another method, like this:
partial class C
{
static partial void M(int i); // defining declaration
static partial void M(int i) // implementing declaration
{
}
}
The crazy part is that the code below is not compiled unless you supply an implementation to the method, and the implementation is not neccesary.
The reasoning behind that is to have light-weight events, that exists only when you "subscribe" to them. The reason for that is the Linq code generation features, which produce a lot of events.
So, this is basically compiler macros again, for a dubious reason at best. I don't think that the language should change because of a tool that it using it. If they want to make any useful changes, there are more than enough suggestions. Method Missing would be welcomed, as well as attributes that can accept useful parameters (i.e, not just String, Int32, Type).
Yuck!
Comments
yuck indeed!
I'm perhaps taking a short-sighted view of this, but why is it yuck?
I thought something like this might be useful to framework developers? :-)
Chris
"I don't think that the language should change because of a tool that it using it."
Calling LINQ a "tool" is probably not fair. Are you just as disappointed about the introduction of extension methods, anonymous types, query expressions, and pretty much everything else in C# 3.5? Because their additions were all driven by the same "tool" - LINQ.
http://msdn.microsoft.com/msdnmag/issues/07/06/CSharp30/default.aspx
My first impression wasn't favorable either... but now I'm thinking I'd like to try it out for a while to see how it goes. I first thought "this is stupid - this is Template Method, we already know how to do this by overriding methods". And then I remembered Paul Graham, and his assertion that a majority (all?) of the GoF Design Patterns were only needed to get past limitations of inferior (not LISP) languages.
So, maybe expansion of the language to be more flexible will allow us to abandon some of our old OO tricks, and that doesn't have to be bad.
But I can't say for sure yet if this is one of those "freeing" features, or just a hack.
Linq is not just an excuse to make questionable concesions. It's better to see it as the vehicle to morph C# into a parallelizable, functional-style language, and put it in better shape to face the trend to multi-core CPUs. (ie. in better shape to not being slower than Erlang :-)
The funny thing is: Anders Hejlsberg hates AOP, however these things are actually trying to do some form of AOP however not in full (so it's not giving you the full AOP featureset).
I agree that they shouldn't butcher C# because their linq to sql needs it. They should design a language and additionally tools but not butcher a language up for their tool, because then you'll get language features which will look stupid in a few years time when the tool becomes obsolete but the language is still there.
Joshua,
I should have been clearer, this feature it added not to support Language Integrated Query, it is added to help the code generator of linq to sql and linq to entities. That is what I object to.
Design Pattens == Code Smell - I agree, except that this isn't really a good solution, it is a half baked one, IMO. It introduce much more complexity to the language, and it is there to solve a stupid problem that can be solved easily in other ways.
Sounds like a great way to make the code less readable.
I suspect there is a ploy to enable a future ioccc contest in C#.....
And after a commenter wrote "This sounds oddly like a c/c++ header file" the author of the post agreed with him.
I'll take your "yuck!" and raise it by "bleh!"
Delusions in I-The-Architect and OR land..
Yuck as an expression of designers of the new world ego.
seen my comments on wes' post just before yours? we should start a petition! hell, i'd pay for it too ;-)
I thought that after some comments on the problems in an earlier post that this was just the solution required - it's not just LINQ, other code generators produce this problem that partial methods can solve, but perhaps there is a better way yet.
Gokhan Altinoren wrote on May 9th about "Designers for ORM Tools"
(http://altinoren.com/PermaLink,guid,75929ea9-d788-462f-9dbd-630a7832734b.aspx):
"One problem here is that it's not easy to modify this kind of generated code. Thanks to 2.0, partial classes help great when adding new functionality, but it's impossible to modify generated getters and setters. DSL Tools is using the term "double derived" for the approach used to solve this problem, use an inherited empty entity instead of the original one around to make it possible to override properties. This model works fine in DSL Tools context but might make real world entities complicated. This one and solutions like this which makes code more bloated are, I believe, the dark side of code generating designers."
I suggest that partial methods are the solution. Are they not?
To follow up on Frans comment,
The C# team do not like interception and are only curious about mixins. The funny thing about this is that they run circles around them to implement different really akward solutions as long as it can't be traced back to AOP.
The reason for not liking interception is because it would confuse the users of the framework/language, the exakt same argument that polymorphism had against itself in the 90's.
I think while their O/R efforts matures, they will quickly learn that not doing it with interceptions and weaving of cross cutting concerns will just bloat everybodies code and be even more confusing in the end.
Or maybe they won't and I'll just switch to java or ruby.
Maybe eveyone forgets that "partial methods" were introduced in C# with the express purpose of enabling design time code generation scenarios. Partial classes allow you to extend what was generated without resorting to modification of the generated code. This allow you to keep redesigning and regenerating w/o clobbering your extensions. Yet, partial classes did not solve everything, since they only let you 'add' new methods and not modify existing ones. Partial methods finish the story. They allow you to specify hook points inside method bodies that enable injection of custom behavior declared in another partial classes. It may not be AOP, but it is very pratical.
Comment preview