what method how generic fun examples delegate c# covariance contravariance

method - how to use func c#



Problema al entender la covarianza contravarianza con genéricos en C# (2)

No puedo entender por qué el siguiente código C # no se compila.

Como puede ver, tengo un método genérico estático Algo con un IEnumerable<T> (y T está restringido para ser una interfaz IA ), y este parámetro no se puede convertir implícitamente a IEnumerable<IA> .

¿Cuál es la explicación? (No busco una solución, solo para entender por qué no funciona).

public interface IA { } public interface IB : IA { } public class CIA : IA { } public class CIAD : CIA { } public class CIB : IB { } public class CIBD : CIB { } public static class Test { public static IList<T> Something<T>(IEnumerable<T> foo) where T : IA { var bar = foo.ToList(); // All those calls are legal Something2(new List<IA>()); Something2(new List<IB>()); Something2(new List<CIA>()); Something2(new List<CIAD>()); Something2(new List<CIB>()); Something2(new List<CIBD>()); Something2(bar.Cast<IA>()); // This call is illegal Something2(bar); return bar; } private static void Something2(IEnumerable<IA> foo) { } }

Error que me sale en la linea Something2(bar) :

Argumento 1: no se puede convertir de ''System.Collections.Generic.List'' a ''System.Collections.Generic.IEnumerable''


El mensaje de error no es suficientemente informativo, y eso es culpa mía. Lo siento por eso.

El problema que está experimentando es una consecuencia del hecho de que la covarianza solo funciona en los tipos de referencia.

Probablemente estés diciendo "pero IA es un tipo de referencia" en este momento. Sí lo es. Pero no dijiste que T es igual a IA . Usted dijo que T es un tipo que implementa IA , y un tipo de valor puede implementar una interfaz . Por lo tanto, no sabemos si la covarianza funcionará, y la rechazamos.

Si desea que la covarianza funcione, debe decirle al compilador que el parámetro type es un tipo de referencia con la restricción de class restricción de la interfaz IA .

El mensaje de error realmente debería decir que la conversión no es posible porque la covarianza requiere una garantía de tipo de referencia, ya que ese es el problema fundamental.


Solo quería complementar la excelente respuesta interna de Eric con un ejemplo de código para aquellos que quizás no estén tan familiarizados con las restricciones genéricas.

Cambie la firma de algo así: class restricción de class tiene que venir primero .

public static IList<T> Something<T>(IEnumerable<T> foo) where T : class, IA