Friday, April 07, 2006

Conflicting Extension Methods

Keith Farmer from the DLinq team replied to my previous post. He pointed out that the problems with extension methods are not only about conflicts with instance methods. You can also get conflicts between extension methods, when several namespaces define extension methods with the same name.

As Keith wrote:

FooCorp's extensions conflict with BarInc's. Yet you use each in non-conflicting manners elsewhere in the same code file. How to do specify which extensions should be applied where, in a way that doesn't always involve doing so at the call site?

It’s a good question. Jon Skeet made a relevant suggestion here, and I presume Microsoft have some ideas up their sleeve too.

Ian Griffiths points out that Microsoft already appear to be segregating extension methods into separate namespaces, and suggests that component vendors should follow suit. E.g. extension methods related to FooSoft.FooLib might be in FooSoft.FooLib.Extensions rather than the main FooSoft.FooLib library. That way, if you don’t want the extensions, you just don’t use FooSoft.FooLib.Extensions.

That separation of extension methods seems like a good thing. Why not get the compiler to enforce it? If extension methods are always in namespaces which contain only extension methods, then you simply don’t use them if you don’t want them.

Can the compiler enforce such separation of extension methods? Yes... almost :-)

In relatively rare cases you may see two (otherwise-unrelated) assemblies defining types in the same namespace. In that situation, the compiler could not enforce the rule, and you’d have to fall back on some other way to resolve conflicts. That’s not as bad as it sounds, since some other syntax (such as this) will still be required anyway to resolve conflicts between extension and interface methods – so why not apply it to the few remaining extension-extension conflicts too?

In all other situations (namespace in a single assembly or in several assemblies with compile-time dependencies on each other) the compiler could enforce the rule.

By the way , what if you just want to use the extension methods from one static type, not from a whole namespace? That’s where Jon’s suggestion comes in. He suggested something like this:

using static BarSoft.BarLib.StringExtender

(where StringExtender is a static class, not a namespace). I wonder if that might be changed to

using MyAlias = BarSoft.BarLib.StringExtender

which is already standard C# syntax and could achieve the same effect? (I.e. only extension methods of the aliased type become accessible, not those in the rest of the namespace.)

This post has been about ideas to make extension-extension conflicts less frequent, and more manageable. I don't think they completely answer Keith's question, in which conflicting extensions were both used in the same code file, but they might help...

I’ll post more on the extension-meets-interface idea soon...


Anonymous Mark Cidade said...

(I was going to post this for the previous post until I noticed the latest post which you say most of what I say here but this also addresses if someone doesn't put extensions in the new namespace)

If you had an instance method that shadowed a newly-introduced extension method that caused a warning, you could avoid the warning by removing the using statement that references that extension's namespace and use fully-qualified names in the same file for any types in that namespace.

e.g., before:

using System;
Foo foo = new Foo();
foo.Method1(arg); //warning: shadows System.NewFooExtensions.Method1()

e.g., after:

//no "using System;"
System.Foo = new System.Foo();
foo.Method1(arg); //no warning

Sat Apr 08, 07:04:00 PM PDT  
Blogger John Rusk said...

Thanks Mark,

Yes, I think I get what you are saying: if all extensions are in their own namespaces, then we can either:

(a) force the call to the extension (using normal static method syntax)


(b) force the call to the instance method, by removing the namespace from our using clauses.


That goes a long way towards addressing all the problems I've raised. I wonder if it would be enough to make compiler warnings feasible...

I still quite like the idea of some kind of finer-grained mechanism (call-site-by-call-site) being available, in addition...

Sun Apr 09, 12:02:00 AM PDT  
Anonymous Mark Cidade said...

Yes, that's right, although extensions don't need to be in their own namespace. It's potentially more convenient if they are, though (so we wouldn't have to fully-qualify any non-extension types used from the same namespace.)

Sun Apr 09, 12:02:00 PM PDT  

Links to this post:

Create a Link

<< Home