C# v3 Extension methods, syntactic sugar for the lack of free functions?

| 7 Comments

There's a lot of noise coming out of the Microsoft PDC right now. Something that interested me was the future direction of C#; you can grab the spec from here.

It seems they're adding "extension methods" which, to me, appear to be just syntactic sugar to make up for the lack of free functions...

In C++ you can have functions that aren't part of an object. In C no functions are part of an object. These are "free" functions. You can't have these kind of things in C# and Java because everything has to be part of an object even if the only purpose for the object's existence is to provide a home for a collection of static methods, go figure...

In C++ a recent idiom is to prefer free functions over object methods where possible. The argument is that creating non-member, non-friend, functions increases encapsulation because these functions don't need access to the object internals and therefore bundling them with the object simply reduces the encapsulation that the object provides by expanding the amount of code that has unnecessary access to the object's internals.

This means that, in modern C++, you may often see things like this:

int ToInt32(const std::string &stringRep);

which can be used like this:
const int i = ToInt32(customerNumber);

Up until now the nearest that you could get to this in C# was something like this:
public class Stuff
{
  public static int ToInt32(string stringRep);
}

which can be used like this:
int i = Stuff::ToInt32(customerNumber);

The new "extension methods" proposal means that the call above can be rendered as this:
int i = customerNumber.ToInt32();

Which, in my mind, is madness. The method is not a member of the object so why should you call it using member syntax? What value does it add to be able to do this? If you're looking to remove the crufty Stuff:: from the front of the call then why not simply allow functions to be defined at namespace scope? Then you could bring the names in with a normal using statement and use them in a way that's expected:
int i = ToInt32(customerNumber);

It's quite clear that ToInt32 comes from a namespace somewhere and isn't a member of the object in question...

So, my question to all you .Net people is why is this new syntax a good thing? I can only see scope for confusion and the eventual banning of this kind of thing in local coding standards...

7 Comments

Eran Sandler seems to agree with me on this...

It looks odd to me too.

But it is not complete madness. Reread Item 32 in
"Exceptional C++" (The interface principle).

I have no problem with extending the 'interface' of a class with 'free functions' and that's just what the current situation in C# is; you extend by creating another class and adding static methods (because you can't create free functions). When this is done it's quite clear where you need to look to find the code and it's quite clear that this code isn't part of the original object.

With this change it's no longer clear where the code lives. Sure the IDE may let you browse to it easily enough but I'm still finding it hard to work out why this change is useful...

Take a look at slide 5 in

http://216.55.183.63/pdc2005/slides/TLN307_Hejlsberg.ppt

My guess is that is needed for the SQL-like
syntax (Query Expressions).

The Csharp 3.0 spec contains the following (in red!)

"Extension methods are less discoverable and more limited in
functionality than instance methods. For those reasons, it is
recommended that extension methods be used sparingly and only in
situations where instance methods are not feasible or possible.
Extension members of other kinds, such as properties, events, and
operators, are being considered but are currently not supported."

Yeah, I agree that's what's driving this; and the auto change in C++ no doubt. And it's good that the C# spec says "don't do this, it's really for us, not you" but that wont stop it being misused. Still, there are lots of language features that are missused...

However, I don't really see why LINQ needs to use extension methods to achieve what it's doing. It's either generating the whole Customer object in which case it can generate what the hell it likes and it doesn't need extension methods, or it isn't and the extension methods can either be part of a derived class or part of an interface. Likewise with the type inference, why is it needed? Why is it so hard to do it without it? It looks, to me, like someone's taking the easy route, by changing the language, but right now there isn't enough information about why to understand the decision process.

I'm sorry, but too many convenient but ultimately broken designs come about simply because not enough thought is given to doing it in a better way; I'm thinking about most of MFC here... Adding questionable language features and poking the crowd who'll rave about how "cool" the new features are isn't an alternative to describing the reasoning behind the decision...

Len,

I think MS chose extension methods for LINQ so that individual classes can, if necessary, provide their own customised alternatives to the standard (extension-based) methods. This comment links to some notes I wrote on this subject.

Your link contains some interesting stuff (especially the follow on posting about the problems), thanks John.

Leave a comment