views:

3886

answers:

7

I'm writing an add-in for ReSharper 4. For this, I needed to reference several of ReSharper's assemblies. One of the assemblies (JetBrains.Platform.ReSharper.Util.dll) contains a System.Linq namespace, with a subset of extension methods already provided by System.Core.

When I edit the code, it creates an ambiguity between those extensions, so that I cannot use OrderBy, for instance. I was wondering how I could solve this? I would like to use the core Linq extensions, and not the ones from ReSharper.

I get the following error when trying to compile:

The call is ambiguous between the following methods or properties: 'System.Linq.Enumerable.OrderBy<string,int>(System.Collections.Generic.IEnumerable<string>, System.Func<string,int>)' and 'System.Linq.Enumerable.OrderBy<string,int>(System.Collections.Generic.IEnumerable<string>, System.Func<string,int>)'

EDIT: I tried the suggestion below, unfortunately without luck. In the meanwhile, I "solved" the problem by removing references to System.Core. This way I could use the extensions provided by ReSharper DLLs.

I uploaded a sample program where I just imported the ReSharper DLLs I needed. I changed the alias of System.Core to SystemCore, added the extern alias directive, but it still didn't work. If I missed something, please let me know. P.S. The references are to ReSharper v4.1 DLLs installed in the default directroy in "C:\Program Files\JetBrains\ReSharper\v4.1\...".

+6  A: 

This is probably one of those rare cases where it makes sense to use an extern alias.

In the properties page for the reference to System.Core (i.e. under References, select System.Core, right-click and select "Properties"), change the "Aliases" value to "global,SystemCore" (or just "SystemCore" if it's blank to start with).

Then in your code, write:

extern alias SystemCore;
using SystemCore::System.Linq;

That will make all the relevant types etc in System.Core.dll's System.Linq namespace available. The name "SystemCore" here is arbitrary - you could call it "DotNet" or something else if that would make it clearer for you.

Jon Skeet
Thanks a lot for the answer, however I still have an issue. I updated my original post.
hmemcpy
It should work fine if you've got the alias specified in the reference. The error you're getting is what I see if I haven't set the "Aliases" property on the reference itself.
Jon Skeet
Thanks again Jon for your help, but unfortunately this still didn't solve the ambiguity issue. Do you have any other suggestions, perhaps?
hmemcpy
So do you have exactly the original problem? If you've *only* got that using directive, you shouldn't have a problem. Could you post a short but complete program which demonstrates the problem (including extern alias)?
Jon Skeet
I uploaded a tiny program with the problem. I know you use ReSharper yourself, Jon, so you probably have the referenced DLLs. Again, thanks a lot! :)
hmemcpy
By the way, this utterly fails in .Net 4.0
Dmitri Nesteruk
+2  A: 

This isn't really an answer, but may provide an easier way for others to reproduce the issue (from the command-line - you could do it with two projects in Visual Studio if you want).

1) Create BadLinq.cs and build it as BadLinq.dll:

using System.Collections.Generic;

namespace System.Linq
{
    public static class Enumerable
    {
        public static IEnumerable<T> Where<T>(this IEnumerable<T> source, 
                                              Func<T,bool> predicate)
        {
            return null;
        }
    }
}

2) Create Test.cs:

extern alias SystemCore;

using System;
using SystemCore::System.Linq;

static class Test
{
    static void Main()
    {
        var names = new[] { "Larry", "Curly", "Moe" };

        var result = names.Where(x => x.Length > 1);
    }
}

3) Compile Test.cs specifying the extern alias:

csc Test.cs /r:BadLinq.dll /r:SystemCore=System.Core.dll

This fails with:

Test.cs(11,28): error CS1061: 'System.Array' does not contain a definition for 'Where' and no extension method 'Where' accepting a first argument of type 'System.Array' could be found (are you missing a using directive or an assembly reference?)

If you change it to not try to use an extension method (i.e. Enumerable.Where) it works fine with the extern alias.

I think this may be a compiler bug. I've emailed a private mailing list which the C# team reads - I'll update this answer or add a new one when I hear back.

Jon Skeet
Hey Jon. I was wondering, out of curiosity, have you got the answer back?
hmemcpy
No, I haven't heard back on this one I'm afraid.
Jon Skeet
A: 

One solution would be to move out to a partial class all your code that uses the ReSharper code. In there, you'd import only the ReSharper namespace and not System.Core. In the rest of the partial class, you'd import all the other namespaces you need, including System.Core, but not the ReSharper namespace.

Fabrice
Thanks for the suggestion, however the ambiguity occurs on the assembly level, not specific class, therefore your suggestion doesn't solve it, unfortunately.
hmemcpy
A: 

While waiting for Jon's answer on my original question, I would like to note that this is no longer an issue, since I am able to use the LINQ extensions, as provided by ReSharper DLLs, even while targeting .NET 3.0.

EDIT: Mr. Skeet was right again! I am able to use full LINQ syntax, while targeting .NET 3.0 in the project's properties and not referencing System.Core!

hmemcpy
You should be able to use LINQ syntax as that just get translated by the compiler. What happens when you try to use a query expression?
Jon Skeet
Hey Jon.Seems that you're right again!, as always ;)I though this was a ReSharper issue, but it isn't! LINQ synax works, System.Core not referenced, DLL is targeted for C# 3.0 :)
hmemcpy
Do you mean targeting .NET 3.0, by the way? You don't target a language version.
Jon Skeet
D'oh! I meant the target framework in project's properties. I haven't fully woke up, I suppose :)
hmemcpy
A: 

Is it possible to specify those extern aliases in an ASP.NET web site? I tried using the compilerOptions attribute of compiler but that does not seem to fully work.

A: 

(Apologies for creating a new answer; if I had 50 reputation points I would have commented on Jon's "BadLinq.cs" post.)

I had the same problem, even with extern alias, and I raised it as a compiler bug on Connect. The workaround for the time being is to forgo extension method syntax.

Ben Challenor
Update: the bug is fixed for VS2010.
Ben Challenor