Resolving extension methods/LINQ ambiguity

2020-01-27 02:48发布

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. How could I 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 DLL files.

I uploaded a sample program where I just imported the ReSharper DLL files 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 DLL files installed in the default directroy in "C:\Program Files\JetBrains\ReSharper\v4.1\...".

10条回答
ら.Afraid
2楼-- · 2020-01-27 02:58

One solution would be to move all your code out to a partial class 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.

查看更多
叛逆
3楼-- · 2020-01-27 02:59

I had a similar situation. After two hours struggling I realized I had duplicate namespace names in my libraries. If you are using file Dynamic.cs published by Microsoft, the only thing you need to do is rename the current namespace to something else, and it will be fixed.

//Copyright (C) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;

namespace System.Linq.Dynamic    <- for example to Linq.Dynamic
{
查看更多
三岁会撩人
4楼-- · 2020-01-27 03:00

In order for ReSharper to be as compatible as possible with the variety of solutions it is used with, it is built against .NET 2.0. LINQ, etc. came in in C# 3.0, so they are not available in that version of the Framework. So, JetBrains added in their own version.

The solution is to build your addin against .NET 2.0 as well.

查看更多
够拽才男人
5楼-- · 2020-01-27 03:06

This is no longer an issue, since I am able to use the LINQ extensions, as provided by ReSharper DLL files, even while targeting .NET 3.0.

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!

查看更多
Emotional °昔
6楼-- · 2020-01-27 03:09

I had the ambiguous reference problem using System.ComponentModel. Visual Studio was complaining that a DLL file exists in both v2 and v4. I was able to resolve it by removing the reference to the System DLL file and readding it.

查看更多
We Are One
7楼-- · 2020-01-27 03:10

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.

查看更多
登录 后发表回答