restricciones - Error de conversión de tipo C#a pesar de la restricción genérica
usando generics c# (3)
¿Por qué, con una restricción genérica en el parámetro de tipo T de clase P de "debe heredar de A", la primera llamada tiene éxito pero la segunda llamada falla con el error de conversión de tipo detallado en el comentario?
abstract class A { }
static class S
{
public static void DoFirst(A argument) { }
public static void DoSecond(ICollection<A> argument) { }
}
static class P<T>
where T : A, new()
{
static void Do()
{
S.DoFirst(new T()); // this call is OK
S.DoSecond(new List<T>()); // this call won''t compile with:
/* cannot convert from ''System.Collections.Generic.List<T>''
to ''System.Collections.Generic.ICollection<A>'' */
}
}
¿No debería la restricción genérica asegurarse de que List<T>
sea realmente ICollection<A>
?
Este es un ejemplo de la falta de covarianza de C # en los tipos genéricos (C # no admite la covarianza de matriz). C # 4 agregará esta característica en los tipos de interfaz y también actualizará varios tipos de interfaz BCL para que también lo admitan.
Por favor vea C # 4.0: Covarianza y Contravarianza :
En este artículo intentaré cubrir una de las innovaciones de C # 4.0. Una de las nuevas características es la covarianza y la contravarianza en los parámetros de tipo que ahora son compatibles con delegados genéricos e interfaces genéricas. Primero veamos qué significan estas palabras :)
Has escrito fuertemente el parámetro para DoSecond como tipo ICollection <A>. A pesar del hecho de que T es de tipo A, en el tiempo de compilación no hay conversión implícita entre List <T> e ICollection <A>. Necesitarás crear la lista y enviarla a ICollection <A> cuando llames a DoSecond, o convertir DoSecond en un método genérico.
NOTA: Este tipo de conversión implícita debería ser compatible con C # 4.0, que proporcionará co / contravariación mucho mejor que lo que C # 3.0 ofrece.
La restricción no tiene ningún efecto sobre el problema; el problema es que está pasando una Lista en un parámetro que requiere ICollection - C # no es compatible con la covarianza, por lo que debe emitir explícitamente la lista a una ICollection:
S.DoSecond((ICollection<A>) new List<T>()); // this call will be happy