2012-10-05 18 views
19

Supongamos que tengo interfaz y clase:Por qué covarianza no funciona con método genérico

public interface ITree {} 
public class Tree : ITree {} 

Como IEnumerable<T> es covariante, la línea de código siguiente se compila con éxito:

IEnumerable<ITree> trees = new List<Tree>(); 

Pero cuando ponerlo en el método genérico:

public void Do<T>() where T : ITree 
{ 
    IEnumerable<ITree> trees = new List<T>(); 
} 

I obtener el error compilado de compilador:

de error 1 No se puede convertir implícitamente el tipo 'System.Collections.Generic.List' a 'System.Collections.Generic.IEnumerable'. existe una conversión explícita (¿falta un yeso?) D: \ Lab \ Lab.General \ Lab.General \ Program.cs 83 40 Lab.General

Por qué covarianza no funciona en este caso?

+0

posible duplicado de [? Es esto un error de covarianza en C# 4] (http://stackoverflow.com/questions/2783233/is-this-a-covariance -bug-in-c-sharp-4) – nawfal

Respuesta

22

Eso es porque la varianza solo funciona con tipos de referencia (clases, interfaces & delegados). Agregar una restricción de clase y que compila bien:

public static void Do<T>() where T : class, ITree 
+1

Gracias, engaño que al hacer la restricción 'T: ITree' está implícito que T es tipo de referencia, pero en realidad no es –

+0

Si' ITree' es un tipo de interfaz, una la ubicación de almacenamiento del tipo 'ITree' siempre mantendrá' null' o una referencia a un objeto heap que implemente 'ITree', pero una ubicación de almacenamiento de un tipo genérico restringido a' ITree' puede contener una referencia o puede contener un valor real instancia de un tipo de valor que implementa 'ITree'. Personalmente, no me gusta la forma en que las estructuras implementan las interfaces se convierten implícitamente en referencias de montón que implementan esas interfaces sin que las estructuras tengan voz en el asunto. La semántica de tipo de valor difiere de la semántica de re-retención en formas ÚTILES, pero ... – supercat

+0

... el modelo de "sistema de tipo unificado" asume (erróneamente) que se comportarán de manera idéntica. Una variable de tipo 'List .Enumerator' implementa' IEnumerable ', pero contiene algo cuyo comportamiento es muy diferente del de una variable del tipo' IEnumerable 'que contiene una referencia a' List .Enumerator'. – supercat

Cuestiones relacionadas