Restricting the use of extension methods?


Having looked through the slides that Vagn pointed me to in a comment to my recent post about C# v3.0 Extension Methods I can understand, a little more, about the reasoning behind the change to the language. Given that the C# v3.0 spec contains the following warning:

"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."

Perhaps it would be a good idea to make classes have to 'opt in' to enable extension methods on them. A keyword, such as extensible or whatever could be added to a class to allow the use of extension methods on it, much in the same way that sealed can be used to prevent extension via inheritance. This would reduce the likelyhood that the feature will be missused by inexperienced programmers and would mean that classes could be 'closed for extension' by design. I would expect much of the .Net framework would naturally be 'closed', in the same way that much of it is 'sealed'. This wouldn't prevent the use of the feature where it was needed but might restrict the confusion that could be caused if it were overused.



Although I like the sound of extension methods in general, there is one item I think could be problematic and should be changed:

From what I've read, the intention is that extension methods will only be used if there is no instance method with the same name and prototype. If an instance methods is present, this will be used instead.

IMO, the compiler should generate an error if you have an extension method which conflicts with an instance method.

For example:

Foo myFoo = new Foo();

If on the above there is an extension method AND an instance method, the compiler should generate an error.

Think about this scenario:
1. You define a ToString() extension method for a particular type (the type being extended possibly originates from a third party library).
2. Your code makes use of this extension method. Builds ok. Test ok. Deploys ok.
3. You receive an update to the third party library. The source class has now had a ToString method added.
4. You re-compile your code with the new library.
5. Your code builds o.k. But hopefully FAILS during your testing. I say hopefully, because of course the worst case is it fails at the customer.

To me, this is exactly the same reasoning behind the use of the new and override keywords for method declarations, i.e. to avoid breaking changes resulting from new versions of components.

I guess there may be some scenarios where this would be difficult/impossible to enforce, for example: What happens when dealing with dynamic types? Inferred types?



I agree there should be an error, I expect there will be. I don't see why it would be a problem to catch this at compile time; but perhaps I'm not thinking about it well enough ;)

Leave a comment