usando tipo restricciones poo parametros parametro objeto lista generico generica crear como clase c# generics type-conversion covariance constraints

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