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