Почему компилятор C # не определяет типы в этом коде автоматически?

Почему компилятор C # не делает вывод о том, что FooExt.Multiply() удовлетворяет сигнатуре Functions.Apply()? Мне нужно указать отдельную переменную делегата типа Func<Foo,int,int>, чтобы код работал ... но похоже, что вывод типа должен справиться с этим. Я ошибся? И если да, то почему?

РЕДАКТИРОВАТЬ: полученная ошибка компиляции:

Аргументы типа для метода FirstClassFunctions.Functions.Apply<T1,T2,TR>(T1, System.Func<T1,T2,TR>, T2)' не могут быть выведены из использования. Попробуйте явно указать аргументы типа

namespace FirstClassFunctions  {
    public class Foo  {
        public int Value { get; set; }

        public int Multiply(int j) {
            return Value*j;
        }
    }

    public static class FooExt  {
        public static int Multiply(Foo foo, int j) {
            return foo.Multiply(j);
        }
    }

    public static class Functions  {
        public static Func<TR> Apply<T1,T2,TR>( this T1 obj, 
                                                Func<T1,T2,TR> f, T2 val ) {
            return () => f(obj, val);
        }
    }


    public class Main  {
        public static void Run()  {
            var x = new Foo {Value = 10};
            // the line below won't compile ...
            var result = x.Apply(FooExt.Multiply, 5);
            // but this will:
            Func<Foo, int, int> f = FooExt.Multiply;
            var result = x.Apply(f, 5);
        }
    }

person CluelessCoder    schedule 15.11.2010    source источник
comment
Следующее должно также работать: x.Apply(new Func<Foo, int, int>(FooExt.Multiply), 5). Что за ошибка компиляции?   -  person thecoop    schedule 16.11.2010
comment
Мне кажется, что он компилируется в .NET 4.0.   -  person Lasse V. Karlsen    schedule 16.11.2010
comment
возможный дубликат C # 3.0 generic вывод типа - передача делегата в качестве параметра функции   -  person thecoop    schedule 16.11.2010
comment
Вы уверены, что это именно тот код, который вы используете? Вы не упростили его для нашей пользы?   -  person Lasse V. Karlsen    schedule 16.11.2010
comment
@Lasse: я подозреваю, что OP компилирует это в VS2008 - где, если я правильно помню, у компилятора C # все еще были некоторые ограничения на разрешение групп методов на основе возвращаемых значений.   -  person LBushkin    schedule 16.11.2010
comment
Значит, компилятор C # 3.0 в 2010 и 2008 годах отличается? Тогда позвольте мне протестировать и 2008 год. Ах, он все еще использует компилятор 4.0, но нацелен на .NET 3.5.   -  person Lasse V. Karlsen    schedule 16.11.2010
comment
Да, компилятор C # 3.0 не справляется с этим, а компилятор 4.0 это делает, даже если нацелен на .NET 3.5.   -  person Lasse V. Karlsen    schedule 16.11.2010
comment
@Lasse: Да. VS 2010 всегда компилирует C # 4.0, даже если ориентирован на .NET 3.5. Это более очевидно при указании ковариации и контравариантности (_1 _ / _ 2_ общие параметры).   -  person Travis Gockel    schedule 16.11.2010
comment
Даже изменение языковой версии в настройках сборки на C # 3.0 не нарушит его. Думаю, это следует рассматривать как ошибку в компиляторе, которая была исправлена ​​с тех пор.   -  person Zooba    schedule 16.11.2010


Ответы (1)


Я считаю, что это результат неспособности компилятора VS2008 C # правильно определить типы, задействованные при преобразовании группы методов в делегат. @Eric Lippert обсуждает это поведение в своем сообщении Вывод типа возвращаемого значения C # 3.0 не работает с группами методов.

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

Правила вывода типов довольно сложны, и я далек от эксперта в этом вопросе. Надеюсь, кто-то с некоторыми реальными знаниями сможет ответить на этот вопрос, если я ошибаюсь.

person LBushkin    schedule 15.11.2010
comment
@ Эрик Липперт: Спасибо за подтверждение. Кстати, мне показалось, что я припоминаю, как вы писали об улучшениях вывода типов в последней версии компилятора C #, но я не могу найти в вашем блоге статьи по этому поводу ... возможно, я это вообразил. - person LBushkin; 16.11.2010
comment
Я упомянул, что мы собираемся исправить это здесь: blogs.msdn.com/b/ericlippert/archive/2008/05/28/ - person Eric Lippert; 17.11.2010