В следующем фрагменте кода я ожидал, что смогу неявно приводить от elements
к baseElements
, потому что TBase
неявно преобразуется в IBase
.
public interface IBase { }
public interface IDerived : IBase { }
public class VarianceBug
{
public void Foo<TBase>() where TBase : IBase
{
IEnumerable<TBase> elements = null;
IEnumerable<IDerived> derivedElements = null;
IEnumerable<IBase> baseElements;
// works fine
baseElements = derivedElements;
// error CS0266: Cannot implicitly convert type
// 'System.Collections.Generic.IEnumerable<TBase>' to
// 'System.Collections.Generic.IEnumerable<IBase>'.
// An explicit conversion exists (are you missing a cast?)
baseElements = elements;
}
}
Однако я получаю сообщение об ошибке, указанное в комментарии.
Цитирование из спецификации:
Тип T<A1, …, An>
может быть преобразован в дисперсию типа T<B1, …, Bn>
, если T
является либо интерфейсом, либо типом делегата, объявленным с параметрами типа варианта T<X1, …, Xn>
, и для каждого параметра типа варианта Xi
one имеет место следующее:
Xi
является ковариантным, и существует неявная ссылка или преобразование идентификатора из Ai
в Bi
Xi
является контравариантным, и существует неявное указание или преобразование идентичности от Bi
до Ai
Xi
является инвариантом, и существует преобразование идентификатора из Ai
в Bi
Проверяя мой код, кажется, что он соответствует спецификации:
IEnumerable<out T>
- это тип интерфейса
IEnumerable<out T>
объявлено с параметрами типа варианта
T
является ковариантным
существует неявное ссылочное преобразование из TBase
в IBase
Итак, это ошибка в компиляторе C # 4?