В следующем фрагменте кода я ожидал, что он сможет неявно отбрасывать от 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?