Почему невозможно вывести вложенные общие типы?

Учитывая следующие классы...

public abstract class FooBase<TBar> where TBar : BarBase{}
public abstract class BarBase{}
public class Bar1 : BarBase{}
public class Foo1 : FooBase<Bar1> {}

... и следующий метод...

public TBar DoSomething<TFoo, TBar>(TFoo theFoo)
    where TFoo : FooBase<TBar>
    where TBar : BarBase
{
    return default(TBar);
}

Почему следующая строка кода не может иметь тип возврата?

Bar1 myBar = DoSomething(new Foo1());

Вместо этого я должен указать общие типы, подобные этому...

Bar1 myBar = DoSomething<Foo1, Bar1>(new Foo1());

Ответы

Ответ 1

Вывод типа метода игнорирует общие ограничения на параметры типа метода (*). Признаки вывода типа метода относятся только к выводам, которые могут быть сделаны путем сравнения аргументов с формальными типами параметров. Поскольку единственным типичным параметром типа, который появляется в ваших формальных типах параметров, является TFoo, невозможно выводить TBar.

Многие считают, что это дизайнерское решение ошибочно, неправильно, неправильно. Хотя я считаю, что это решение действительно приводит к тому, что, на мой взгляд, имеет хорошие свойства. Для расширенной дискуссии по этому вопросу см. Комментарии или комментарии в этой статье в блоге, в которых говорится, что я ошибаюсь, неправильно, неправильно:

http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx


(*) Заметим, что я сказал, что ограничения на параметры типа метода игнорируются, а не ограничения вообще. Если выведенные формальные типы параметров создаются такими типовыми типами, что конструкция нарушает их ограничения на параметры типа, то этот факт приводит к ошибке вывода типа, и этот метод не является кандидатом на разрешение перегрузки. Но ни при каких обстоятельствах мы не делаем вывод из ограничения, отличного от "Хм, ясно, что это не сработает".