Ошибка Visual Studio, разрешающая лямбду в методе с перегрузками делегатов Func? - PullRequest
4 голосов
/ 30 марта 2012

Я столкнулся со странным поведением в Visual Studio 2010 при использовании анонимных методов в функциях, которые перегружены различными делегатами Func.

Ниже я создал небольшой класс воспроизведения.

Рассмотрим этот класс ListViewAdapter

namespace LambdaTestApp
{
    public class ListViewAdapter<T>
    {
        private Func<int, string, int, string> _converter1;
        private Func<RefType1, string, string> _converter2;

        public ListViewAdapter(int arg1, Func<int, string, int, string> converter) 
        {
            _converter1 = converter;
        }

        public ListViewAdapter(int arg1, Func<RefType1, string, string> converter) 
        {
            _converter2 = converter;
        }

        public static ListViewAdapter<T> MockPopulate(int arg, Func<int, string, int, string> converter) {

            ListViewAdapter<T> instance = new ListViewAdapter<T>(arg, converter);

            return instance;
        }

        public static ListViewAdapter<T> MockPopulate(int arg, Func<RefType1, string, string> converter)
        {
            ListViewAdapter<T> instance = new ListViewAdapter<T>(arg, converter);
            return instance;
        }
    }

    public class RefType1
    {
        public string Property1 { get; set; }
    }
}

И этот следующий код, который использует перегрузку с лямбда-выражением:

namespace LambdaTestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            ListViewAdapter<RefType1>.MockPopulate(1, (item, str) =>
            {
                var myItem = item;
                return str;
            });
        }
    }
}

Это должно разрешиться до Func<RefType1, string, string>первый аргумент должен быть RefType1, однако проблема в том, что вместо item, являющегося RefType1, Visual Studio видит его как int.

Вопрос: существует ли допустимое преобразование между делегатами Func?это не очевидно, или это ошибка Visual Studio IntelliSense?

Ответы [ 3 ]

5 голосов
/ 14 апреля 2012

Я бы лично согласился, что это ошибка - или, по крайней мере, недостаток . Даже если он отображается только в том случае, если код недопустим - и только в том случае, если код в лямбда-выражении недопустим - я думаю, что для Intellisense было бы более уместно просмотреть часть объявления параметров лямбда-выражения (часть до =>) завершена, и работа основана на этой информации.

Нет ничего, что вы могли бы поместить в тело лямбда-выражения, которое изменило бы разрешение перегрузки таким образом, чтобы сделать выбор Func<int, string, int, string> действительным ... просто не хватает параметров .

Я бы по крайней мере предложил бы занести в журнал проблему Connect по этому поводу - она ​​вполне может "работать как задумано" с точки зрения "MS не спроектировал ее, чтобы справиться с этим". сценарий ", но это может явно работать лучше. Обратите внимание, что он все еще работает в бета-версии VS11, хотя по общему признанию ноутбук, на котором я сейчас работаю, не применил последнее обновление к бета-версии. Я не удивлюсь, если вы получите ответ «Да, это было бы неплохо, но потребовалось бы огромное количество работы за небольшую выгоду», но в любом случае это стоит повысить, ИМО.

2 голосов
/ 12 апреля 2012

Он должен разрешиться до Func<RefType1, string, string>, а первый аргумент должен быть RefType1, однако проблема в том, что вместо элемента RefType1 Visual Studio видит его как int.

Visual Studio угадывает как int, пока существует ошибка компиляции, посмотрев на первую из перегруженных функций. Он не может определить, какая перегрузка используется, потому что не может понять код. Возможно, он сможет лучше угадать, что именно вы имели в виду , вероятно , но это довольно сложно считать ошибкой.

Когда вы исправляете ошибку, Visual Studio может сказать, что тип аргумента RefType1. Вы можете убедиться в этом, убедившись, что код скомпилирован, а затем наведя указатель мыши на item.

Да, к сожалению, это означает, что, поскольку ввод . по крайней мере временно сделает код недействительным и отобразит элементы int. Если вам действительно нужно, вы можете вызвать item.ToString(); способом, который удовлетворяет компилятору, а затем переписать . новым .. Затем вы увидите список, на который вы надеетесь.

В качестве альтернативы, убедитесь, что ваша наиболее часто используемая перегрузка указана первой, чтобы Visual Studio по-другому угадывал.

0 голосов
/ 30 марта 2012

Разрешение перегрузки метода для LINQ работает точно , как и для C #: основано на количестве и типах аргументов, и ничего более.Независимо от того, является ли аргумент универсальным, значение не имеет.

Не видя код в PopulateListView, я бы сказал, что вы передаете int, и это то, что вы получаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...