C# 解决扩展方法/LINQ 歧义
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/453451/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Resolving extension methods/LINQ ambiguity
提问by Igal Tabachnik
I'm writing an add-in for ReSharper4. 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.
我正在为ReSharper4编写插件。为此,我需要引用 ReSharper 的几个程序集。其中一个程序集 (JetBrains.Platform.ReSharper.Util.dll) 包含一个System.Linq
命名空间,其中包含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 LINQextensions, and not the ones from ReSharper.
例如,当我编辑代码时,它会在这些扩展名之间产生歧义,因此我无法使用OrderBy
. 我怎么能解决这个问题?我想使用核心LINQ扩展,而不是来自 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>
)'
以下方法或属性之间的调用不明确:'
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.
编辑:我尝试了下面的建议,不幸的是没有运气。同时,我通过删除对System.Core
. 这样我就可以使用 ReSharper DLL 文件提供的扩展。
I uploaded a sample programwhere 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\..."
.
我上传了一个示例程序,我只是在其中导入了我需要的 ReSharper DLL 文件。我更改了System.Core
to的别名SystemCore
,添加了extern alias
指令,但它仍然不起作用。如果我错过了什么,请告诉我。PS 引用的是安装在默认目录中的 ReSharper v4.1 DLL 文件"C:\Program Files\JetBrains\ReSharper\v4.1\..."
.
采纳答案by Igal Tabachnik
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.
这不再是一个问题,因为我能够使用 ReSharper DLL 文件提供的 LINQ 扩展,即使是针对 .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!
斯基特先生又是对的!我能够使用完整的 LINQ 语法,同时在项目的属性中针对 .NET 3.0 而不是引用 System.Core!
回答by Jon Skeet
This is probably one of those rare cases where it makes sense to use an extern alias.
这可能是使用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).
在 System.Core 引用的属性页面中(即在 References 下,选择 System.Core,右键单击并选择“Properties”),将“Aliases”值更改为“global,SystemCore”(如果一开始是空白的)。
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.
这将使 System.Core.dll 的 System.Linq 命名空间中的所有相关类型等可用。此处的“SystemCore”名称是任意的 - 您可以将其称为“DotNet”或其他名称,如果这会让您更清楚。
回答by Jon Skeet
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).
这不是真正的答案,但可能为其他人提供了一种更简单的方法来重现问题(从命令行 - 如果需要,您可以在 Visual Studio 中使用两个项目来完成)。
1) Create BadLinq.cs and build it as BadLinq.dll:
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) Create Test.cs:
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) Compile Test.cs specifying the extern alias:
3) 编译 Test.cs 指定 extern 别名:
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?)
Test.cs(11,28): 错误 CS1061: 'System.Array' 不包含 'Where' 的定义,并且找不到接受类型为 'System.Array' 的第一个参数的扩展方法 'Where'(是吗?缺少 using 指令或程序集引用?)
If you change it to not try to use an extension method (i.e. Enumerable.Where) it works fine with the extern alias.
如果您将其更改为不尝试使用扩展方法(即 Enumerable.Where),则它可以与 extern 别名一起正常工作。
I think this maybe 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.
我认为这可能是一个编译器错误。我已经通过电子邮件发送了 C# 团队阅读的私人邮件列表 - 我会更新此答案或在收到回复时添加一个新答案。
回答by Fabrice
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.
一种解决方案是将所有代码移到使用 ReSharper 代码的分部类中。在那里,您将只导入 ReSharper 命名空间而不是 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.
在部分类的其余部分中,您将导入所需的所有其他命名空间,包括 System.Core,但不导入 ReSharper 命名空间。
回答by Ben Challenor
I had the same problem, even with extern alias, and I raised it as a compiler bugon Connect. The workaround for the time being is to forgo the extension method syntax.
我遇到了同样的问题,即使使用 extern 别名,我也将其作为Connect 上的编译器错误提出。暂时的解决方法是放弃扩展方法语法。
The bug is fixed for Visual Studio 2010.
该错误已针对 Visual Studio 2010 修复。
回答by DOHXEHAPO
It is really a compiler error.
这确实是一个编译器错误。
I had the same problem, and I solved it just by cleaning and rebuilding the project. After that the problem disappeared.
我遇到了同样的问题,我只是通过清理和重建项目来解决它。之后问题就消失了。
回答by Nick Chadwick
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.
为了让 ReSharper 尽可能与其所使用的各种解决方案兼容,它是针对 .NET 2.0 构建的。LINQ 等在 C# 3.0 中出现,因此它们在该版本的框架中不可用。因此,JetBrains 添加了他们自己的版本。
The solution is to build your addin against .NET 2.0 as well.
解决方案是也针对 .NET 2.0 构建您的插件。
回答by Ujain
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.
我在使用 System.ComponentModel 时遇到了模棱两可的参考问题。Visual Studio 抱怨 v2 和 v4 中都存在一个 DLL 文件。我能够通过删除对系统 DLL 文件的引用并读取它来解决它。
回答by Ryan
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.
我也有类似的情况。经过两个小时的努力,我意识到我的库中有重复的命名空间名称。如果您使用的是 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
{
回答by Joey Morgan
I found this same sort of ambiguity when use PagedList in MVC (.Net 4.5, MVC 5). I found that if I took the object for the argument that was ambiguous and cast it explicitly first, the problem was resolved. To if the ambiguity was between a method that takes System.Linq.Enumerable and one that takes System.Collections.Generic.IEnumerable as the parameter in question, and the source is of type System.Collections.Generic.IEnumerable, I don't use the extension method on it. I cast it.In this example, my repository method returns a List:
在 MVC (.Net 4.5, MVC 5) 中使用 PagedList 时,我发现了同样的歧义。我发现如果我将对象作为不明确的参数并首先明确地转换它,问题就解决了。如果歧义是在采用 System.Linq.Enumerable 的方法和采用 System.Collections.Generic.IEnumerable 作为相关参数的方法之间,并且源是 System.Collections.Generic.IEnumerable 类型,我不知道使用扩展方法就可以了。我投了它。在这个例子中,我的存储库方法返回一个列表:
searchRequest.CaseSearchResults = csr.SelectMatchingCases(searchRequest);
var results = searchRequest.CaseSearchResults.AsEnumerable<CaseSearchResult>();
int pageNum = (int)(ViewBag.PageNum ?? 1);
var pageResults =results.ToPagedList<CaseSearchResult>(pageNum, 5);
Calling the extension method on searchRequest.CaseSearchResultscaused the ambiguity error; explicitly casting to resultsand then calling the extension on that worked.
在searchRequest.CaseSearchResults上调用扩展方法导致歧义错误;显式转换为结果,然后调用扩展名。