解决扩展方法/ LINQ歧义

时间:2009-01-17 15:34:11

标签: c# .net visual-studio-2008 linq extension-methods

我正在为ReSharper编写一个加载项.4。为此,我需要引用几个ReSharper的程序集。其中一个程序集(JetBrains.Platform.ReSharper.Util.dll)包含一个System.Linq命名空间,其中一部分扩展方法已由System.Core提供。

当我编辑代码时,它会在这些扩展之间产生歧义,因此我不能使用OrderBy。我该怎么解决这个问题?我想使用核心LINQ扩展名,而不是ReSharper中的扩展名。

尝试编译时出现以下错误:

  

电话之间的暧昧不明确   以下方法或属性:   “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>)'

编辑:我尝试了下面的建议,遗憾的是没有运气。同时,我通过删除对System.Core的引用来“解决”问题。这样我就可以使用ReSharper DLL文件提供的扩展。

uploaded a sample program我刚刚导入了我需要的ReSharper DLL文件。我将System.Core的别名更改为SystemCore,添加了extern alias指令,但它仍然无效。如果我错过了什么,请告诉我。 附:引用是安装在"C:\Program Files\JetBrains\ReSharper\v4.1\..."中默认directroy中的ReSharper v4.1 DLL文件。

10 个答案:

答案 0 :(得分:41)

这可能是使用extern alias时很少见的极少数情况之一。

在System.Core引用的属性页面中(即在References下,选择System.Core,右键单击并选择“Properties”),将“Aliases”值更改为“global,SystemCore”(或只是“ SystemCore“如果它开始是空白的。”

然后在你的代码中写下:

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

这将使System.Core.dll的System.Linq命名空间中的所有相关类型等可用。这里的名称“SystemCore”是任意的 - 你可以称之为“DotNet”或其他东西,如果这样可以让你更清楚。

答案 1 :(得分:6)

这不是一个真正的答案,但可能为其他人提供了一种更简单的方法来重现问题(从命令行 - 如果需要,可以在Visual Studio中使用两个项目)。

1)创建BadLinq.cs并将其构建为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)创建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)编译Test.cs,指定extern别名:

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

这失败了:

  

Test.cs(11,28):错误CS1061:   'System.Array'不包含   'Where'和no的定义           扩展方法'where'接受类型的第一个参数   可以找到'System.Array'           (您是否缺少using指令或程序集引用?)

如果你把它改为不尝试使用扩展方法(即Enumerable.Where),它可以使用extern别名。

我认为可能是编译器错误。我已经通过电子邮件发送了一个C#团队阅读的私人邮件列表 - 我会在收到回复后更新此答案或添加新答案。

答案 2 :(得分:2)

这不再是一个问题,因为我能够使用ReSharper DLL文件提供的LINQ扩展,即使在定位.NET 3.0时也是如此。

先生。 Skeet再次正确!我可以使用完整的LINQ语法,同时在项目的属性中定位.NET 3.0,而不是引用System.Core!

答案 3 :(得分:2)

为了使ReSharper尽可能与其使用的各种解决方案兼容,它是针对.NET 2.0构建的。 LINQ等来自C#3.0,因此它们在该版本的Framework中不可用。所以,JetBrains加入了他们自己的版本。

解决方案是构建针对.NET 2.0的插件。

答案 4 :(得分:1)

我使用System.ComponentModel存在模糊的引用问题。 Visual Studio抱怨v2和v4中都存在DLL文件。我能够通过删除对系统DLL文件的引用并读取它来解决它。

答案 5 :(得分:0)

一种解决方案是将所有代码移出到使用ReSharper代码的部分类。在那里,您只导入ReSharper命名空间而不导入System.Core。

在部分类的其余部分中,您将导入所需的所有其他命名空间,包括System.Core,但不导入ReSharper命名空间。

答案 6 :(得分:0)

我遇到了同样的问题,即使是extern别名,我在Connect上也是raised it as a compiler bug。目前的解决方法是放弃扩展方法语法。

Visual Studio 2010修复了该错误。

答案 7 :(得分:0)

这确实是一个编译器错误。

我遇到了同样的问题,我只是通过清理和重建项目来解决它。之后问题就消失了。

答案 8 :(得分:0)

我有类似的情况。经过两个小时的努力,我意识到我的库中有重复的命名空间名称。如果您使用的是Microsoft发布的Dynamic.cs文件,那么您唯一需要做的就是将当前命名空间重命名为其他名称,并且它将被修复。

//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
{

答案 9 :(得分:0)

在MVC(.Net 4.5,MVC 5)中使用PagedList时,我发现了同样的歧义。我发现如果我把对象用于不明确的参数并首先明确地转换它,问题就解决了。如果模糊性介于采用System.Linq.Enumerable的方法和采用System.Collections.Generic.IEnumerable作为参数的方法之间,并且源类型为System.Collections.Generic.IEnumerable,我不会使用扩展方法。我投了它。在这个例子中,我的存储库方法返回一个List:

searchRequest.CaseSearchResults = csr.SelectMatchingCases(searchRequest);
var results = searchRequest.CaseSearchResults.AsEnumerable<CaseSearchResult>();
int pageNum = (int)(ViewBag.PageNum ?? 1);
var pageResults =results.ToPagedList<CaseSearchResult>(pageNum, 5);

searchRequest.CaseSearchResults 上调用扩展方法会导致歧义错误;明确地转换为结果,然后调用该扩展程序。