Подтвердить что ты не робот

Открытые общие аргументы типа нельзя вывести из использования

В этом вопросе, упоминая компилятор, я на самом деле ссылаюсь на компилятор Roslyn. Проблема возникает при использовании IntelliSense, который считается одним и тем же компилятором.

Для демонстрационных целей и полноты используются следующие классы (с использованием Visual Studio 2015 с С# 6.0 и .NET 4.6.1):

public class A
{
    public IEnumerable<B> B { get; set; }
}
public class B
{
    public IEnumerable<C> C { get; set; }
}
public class C { }
public class Helper<T> { }

Ниже приведен следующий метод расширения:

public static void FooBar<T1, T2>(
    this Helper<IEnumerable<T1>> helper,
    Expression<Func<T1, IEnumerable<T2>>> expression) { ... }

Компилятор способен вывести его при потреблении следующим образом:

Helper<IEnumerable<B>> helper = ...;
helper.FooBar(l => l.C); //T1 is B and T2 is C

Также смотрите этот перегруженный метод расширения:

public static void FooBar<T1, T2, T3>(
    this Helper<T1> helper,
    Expression<Func<T1, IEnumerable<T2>>> expression1,
    Expression<Func<T2, IEnumerable<T3>>> expression2) { ... }

Компилятор НЕ может вывести T1 при вводе его следующим образом:

Helper<A> helper = ...;
helper.FooBar(l => l. //compiler/IntelliSense cannot infer that T1 is A

Этот пример скриншота будет описывать больше того, что я имею в виду, не имея возможности сделать вывод:
введите описание изображения здесь

Также я получаю это сообщение об ошибке при наведении указателя мыши на метод расширения с помощью мыши (я заменил символы < и > [ и ] соответственно, потому что StackOverflow не может форматировать их цитата):

Аргументы типа для метода FooBar [T1, T2] (этот помощник [IEnumerable [T1]], выражение [Func [T1, IEnumerable [T2]]]) не могут быть выведены от использования. Попробуйте явно указать аргументы типа.

Но когда он выполняется вручную, выполните следующие действия:

helper.FooBar(l => l.B, l => l.C); //compiler infers that T1 is A, T2 is B and T3 is C

компилятор счастлив.

Почему компилятор /IntelliSense (или функция автозаполнения Visual Studio) не вычисляет T1 и не хочет, чтобы я явно указывал аргументы типа при вводе?

Обратите внимание, что если я опускаю IEnumerable<> всюду в своих примерах, компилятор может с радостью сделать вывод во время ввода. Компилятор также счастлив после ввода вручную l => l.B. Затем он знает T1 is A, поэтому вы можете выразить последний аргумент с помощью IntelliSense.

4b9b3361

Ответ 1

Если я правильно вас понял, все работает как ожидалось для меня в VS2013:

Ваш первый случай:

Ваш второй случай:

Я начинаю вводить l., и IntelliSense показывает мне, что l имеет свойство B, которое можно использовать. Поэтому, если я прав, а правильно отображается в VS2013, тогда как не выводит в VS2015, тогда это определенно ошибка в VS2015 IntelliSense, о которой можно сообщить в Microsoft.

Ответ 2

Я нашел ваш вопрос интересным, и поскольку я использую VS 2015, я думал, что смогу попробовать и его. Я получил ту же ошибку, что и вы, поэтому я думаю, что это может быть ошибка VS, поскольку в других версиях она работает правильно.

Вот моя ошибка:

введите описание изображения здесь

И у меня также нет предложений по CTRL + SPACE.

EDIT:

Аналогичную ошибку можно увидеть здесь.

Итак, поскольку в более старых версиях VS это работает, то именно по этой причине его можно считать ошибкой.

Ответ 3

Как я уже сказал, у меня была та же проблема.здесь отчет об ошибке)
Это не связано с выражениями или IEnumerable. Вот упрощенный пример

using System;

namespace ConsoleApplicationExpressionTree
{

    public static class Extentions
    {
        static void Main() { }
        static void AMethod(string[] args)
        {
            SetValue(new Customer(), e => e.Name   /*type here */, "TheName");

        }

        public static void SetValue<TEntity, TProperty>(TEntity instance, Func<TEntity, TProperty> expression, TProperty newValue)
        {

        }
    }
    public class Customer
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

Я только заметил, что если вы удалите третий аргумент из метода, который он работает!!!

using System;

namespace ConsoleApplicationExpressionTree
{

    public static class Extentions
    {
        static void Main() { }
        static void AMethod(string[] args)
        {
            SetValue(new Customer(), e => e.Name   /*type here */);

        }

        public static void SetValue<TEntity, TProperty>(TEntity instance, Func<TEntity, TProperty> expression)
        {

        }
    }
    public class Customer
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

Итак, если вам очень повезло, вы можете исправить свой текущий пример, изменив параметры.
Если нет, вам просто придется ждать MS, чтобы исправить это...