Разрешение методов расширения / неоднозначность LINQ

Я пишу надстройку для 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.

Я загрузил пример программы, в которую я только что импортировал нужные мне файлы DLL ReSharper. Я изменил псевдоним System.Core в SystemCore, добавил extern alias директива, но это все еще не сработало. Если я что-то пропустил, пожалуйста, дайте мне знать. PS Ссылки относятся к файлам DLL ReSharper v4.1, установленным в директории по умолчанию в "C:\Program Files\JetBrains\ReSharper\v4.1\...",

10 ответов

Решение

Это больше не проблема, так как я могу использовать расширения LINQ, предоставляемые файлами ReSharper DLL, даже при нацеливании на.NET 3.0.

Мистер Скит снова был прав! Я могу использовать полный синтаксис LINQ, ориентируясь на.NET 3.0 в свойствах проекта и не ссылаясь на System.Core!

Это, вероятно, один из тех редких случаев, когда имеет смысл использовать внешний псевдоним.

На странице свойств для ссылки на System.Core (то есть в разделе "Ссылки" выберите System.Core, щелкните правой кнопкой мыши и выберите "Свойства"), измените значение "Псевдонимы" на "global,SystemCore" (или просто "SystemCore", если пусто для начала)

Затем в своем коде напишите:

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

Это сделает все соответствующие типы и т.д. в пространстве имен System.Core.dll System.Linq доступными. Название "SystemCore" здесь произвольно - вы можете назвать его "DotNet" или что-то еще, если это сделает его более понятным для вас.

На самом деле это не ответ, но он может предоставить другим более простой способ воспроизвести проблему (из командной строки - вы можете сделать это с двумя проектами в 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, указав внешний псевдоним:

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

Это не с:

Test.cs (11,28): ошибка CS1061: "System.Array" не содержит определения "Где", и отсутствует метод расширения "Где", принимающий первый аргумент типа "System.Array" (вы отсутствует директива использования или ссылка на сборку?)

Если вы измените его, чтобы не пытаться использовать метод расширения (т.е. Enumerable.Where), он отлично работает с внешним псевдонимом.

Я думаю, что это может быть ошибка компилятора. Я отправил по электронной почте частный список рассылки, который читает команда C# - я обновлю этот ответ или добавлю новый, когда получу ответ.

Чтобы ReSharper был максимально совместим с различными решениями, с которыми он работает, он построен на.NET 2.0. LINQ и т. Д. Появились в C# 3.0, поэтому они недоступны в этой версии Framework. Итак, JetBrains добавлен в собственную версию.

Решение состоит в том, чтобы также создать свой плагин для.NET 2.0.

У меня была неоднозначная проблема с использованием System.ComponentModel. Visual Studio жаловалась, что файл DLL существует как в v2, так и в v4. Я смог решить эту проблему, удалив ссылку на файл System DLL и прочитав ее.

Это действительно ошибка компилятора.

У меня была та же проблема, и я решил ее, просто очистив и восстановив проект. После этого проблема исчезла.

У меня была такая же проблема, даже с внешним псевдонимом, и я поднял ее как ошибку компилятора в Connect. Обходной путь в настоящее время должен отказаться от синтаксиса метода расширения.

Ошибка исправлена ​​для Visual Studio 2010.

Я обнаружил такую ​​же двусмысленность при использовании PagedList в MVC (.Net 4.5, MVC 5). Я обнаружил, что если я возьму объект за аргумент, который был неоднозначным, и сначала приведу его явно, проблема будет решена. Если неоднозначность была между методом, который принимает 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 вызвал ошибку неоднозначности; явное приведение к результатам, а затем вызов расширения для того, что сработало.

Одним из решений было бы переместить весь ваш код в частичный класс, который использует код ReSharper. Там вы бы импортировали только пространство имен ReSharper, а не System.Core.

В оставшейся части неполного класса вы импортируете все другие необходимые вам пространства имен, включая System.Core, но не пространство имен ReSharper.

У меня была похожая ситуация. После двух часов борьбы я понял, что в моих библиотеках есть повторяющиеся имена пространств имен. Если вы используете файл Dynamic.cs, опубликованный Microsoft, единственное, что вам нужно сделать, это переименовать текущее пространство имен в другое, и оно будет исправлено.

//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
{
Другие вопросы по тегам