positiva - ¿Es esto un error de covarianza en C#4?
varianza y covarianza definicion (2)
En el siguiente fragmento de código, esperaba poder convertir implícitamente elements en elements baseElements porque TBase es implícitamente convertible a 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;
}
}
Sin embargo, obtengo el error que se menciona en el comentario.
Citando de la especificación:
Un tipo
T<A1, …, An>es convertible en varianza a un tipoT<B1, …, Bn>siTes una interfaz o un tipo de delegado declarado con los parámetros de tipo de varianteT<X1, …, Xn>, y para cada parámetro de tipo de varianteXise cumple una de las siguientes condiciones:
Xies covariante y existe una referencia implícita o conversión de identidad deAiaBi
Xies contravariante y existe una referencia implícita o conversión de identidad deBiaAi
Xies invariante y existe una conversión de identidad deAiaBi
Comprobando mi código, parece ser consistente con la especificación:
IEnumerable<out T>es un tipo de interfazIEnumerable<out T>se declara con parámetros de tipo de varianteTes covarianteexiste una conversión de referencia implícita de
TBaseaIBase
Entonces, ¿es un error en el compilador C # 4?
La varianza solo funciona para tipos de referencia (o hay una conversión de identidad ). No se sabe que TBase es un tipo de referencia, a menos que agregue : class :
public void Foo<TBase>() where TBase : class, IBase
ya que podría escribir un:
public struct Evil : IBase {}
Marc tiene razón, estaba a punto de pegar la misma respuesta.
Vea las Preguntas Frecuentes de Covarianza y Contravarianza:
http://blogs.msdn.com/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx
De las preguntas frecuentes:
"La varianza solo se admite si un parámetro de tipo es un tipo de referencia".
La varianza no es compatible con los tipos de valores
Lo siguiente no compila tampoco:
// int is a value type, so the code doesn''t compile.
IEnumerable<Object> objects = new List<int>(); // Compiler error here.