В следующем фрагменте кода я ожидал, что он сможет неявно отбрасывать от 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один имеет место следующее:
Xiявляется ковариантным и существует неявное обращение ссылки или идентичности отAiдоBi
Xiявляется контравариантным и существует неявное обращение ссылки или идентичности отBiдоAi
Xiявляется инвариантным и существует тождественное преобразование отAiдоBi
Проверка моего кода, похоже, соответствует спецификации:
-
IEnumerable<out T>- тип интерфейса -
IEnumerable<out T>объявляется с параметрами типа варианта -
Tявляется ковариантным -
существует неявное ссылочное преобразование от
TBaseдоIBase
Итак - это ошибка в компиляторе С# 4?