Вывод типа C #: терпит неудачу, где это не должно? - PullRequest
4 голосов
/ 09 февраля 2009

Обратите внимание на следующий код. Оскорбительная строка была закомментирована.

interface I<R> { }

class C : I<int> { }

class Program
{
    private static void function<T, R>(T t) where T : class, I<R>
    {
    }

    static void Main(string[] args)
    {
        // function(new C()); // wont compile
        function<C, int>(new C());
    }
}

Я считаю, что вывод типа должен определить тип, потому что аргумент T предоставляет первый тип, в то время как I<R> предоставляет второй тип.

Есть ли способ изменить дизайн функции, чтобы вызывающим абонентам не приходилось указывать типы?

Ответы [ 5 ]

8 голосов
/ 09 февраля 2009

Нет, если вы хотите сохранить все ограничения. Тем не менее, это должно служить одинаково хорошо, если у вас нет особых причин запрещать типы значений:

private static void function<R>(I<R> t)
5 голосов
/ 09 февраля 2009

Существуют различные способы добавления дополнительных правил к выводу типов - биты логики, которые может применять человек, но которых компилятор (подчиняющийся спецификации языка) не делает.

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

Однако, чтобы выдвинуть противоположное мнение - некоторые языки (особенно функциональные) имеют более мощные механизмы вывода типов. Здесь всегда есть плюсы и минусы - я считаю, что одно из преимуществ текущей системы логического вывода в C # заключается в том, что она всегда делает успехи или останавливается, например - В блоге Эрика Липперта есть больше информации по этому и ряду других типов вывода вопросов.

4 голосов
/ 09 февраля 2009
class D : I<int>, I<string> { }
//
function<D, int>(new D());
function<D, string>(new D());
//is R int or string?
function(new D());  
1 голос
/ 09 февраля 2009

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

class Other : I<int>, I<Student>{ ... }
void Example(){
  function(new D());
}

В этом случае есть двусмысленность относительно того, какой я должен быть выбран.

Если вы ожидаете C # 4.0, проблема только возрастает с добавлением новых функций дисперсии.

1 голос
/ 09 февраля 2009

Нет, C # не поддерживает такого рода выводы.

Используйте непосредственно интерфейс и найдите тип с помощью get type ..

private static void function<R>(I<R> t)
{
   Type typeofT = typeof(T);
}

не может сделать лучше.

Если вам нужно вызвать другой обобщенный метод с помощью T, вы можете создать обобщенный вызов с помощью отражения, используя typeofT Type.

...