2012-06-20 11 views
9

tengo este código simple:.NET covarianza

public interface IReader<out T> 
{ 
    IEnumerable<T> GetData(); 
} 

Esta interfaz debe ser covariante en T, y estoy usando de esta manera:

private static Func<bool> MakeSynchroFunc<T>(IReader<T> reader) where T : IComposite 
{ 
    return() => Synchronize(reader); 
} 

nota la restricción de T para poner en práctica IComposite. El método de sincronización toma un IReader<IComposite> de entrada:

private static bool Synchronize(IReader<IComposite> reader) 
{ 
    // ...... 
} 

El compilador me dice que no se puede convertir de IReader<T> a IReader<IComposite> a pesar de la restricción en T y la covarianza de ireader.

¿Hay algo que esté haciendo mal aquí? El compilador debería poder verificar la restricción y la covarianza debería permitirme usar mi IReader<T> como IReader<Icomposite>, ¿o no?

Gracias.

+3

¿Y si 'T' fuera una estructura? Entonces las reglas de varianza se romperían. Necesita una restricción de 'clase' para satisfacer al compilador de que será una conversión que preserva la identidad. Ver: [¿Es esto un error de covarianza en C# 4?] (Http://stackoverflow.com/questions/2783233/is-this-a-covariance-bug-inc-c-sharp-4) – Ani

+0

sí, ese fue el problema, funciona bien ahora. gracias –

+0

posible duplicado de [¿Por qué la covarianza no funciona con el método genérico] (http://stackoverflow.com/questions/12743444/why-covariance-does-not-work-with-generic-method) – nawfal

Respuesta

5

Debería poder resolver su problema agregando una restricción class al T. La covarianza no funciona cuando las estructuras están involucradas (IEnumerable<int> no sería convertible a IEnumerable<object>). Dado que no ha restringido T para ser una clase, puede pasar un IReader<some struct that implements IComposite>, que no sería convertible.

+0

genial, funciona ahora, ya sabía que la covarianza no funcionaba con tipos de valores, pero no me di cuenta de que esta era la causa de mi problema en este caso. agregar la restricción de clase hace que funcione perfectamente. gracias !! –

1

Desafortunadamente no. Los genéricos no son covariantes. IReader<T> y IReader<IComposite> son tipos totalmente no relacionados, a pesar de que T está relacionado con IComposite.

EDIT: No sé por qué esto no funcionaría con .Net 4 y <out T>. ¿Alguien más puede responder?

+1

¿estás seguro? el especificador de salida en la definición de interfaz de IReader debe decirle al compilador que la interfaz es covariante. Estoy usando .NET 4 –

+3

Esta respuesta necesita aclaración; es bastante confuso como está escrito. –

+0

No sabía acerca de la palabra clave para la covarianza de la interfaz, y habiendo leído sobre ella no puedo entender por qué el código del OP no funcionaría. +1 por pregunta, ya que aprendí algo, y espero que alguien más pueda responder. – GazTheDestroyer

0

por qué no cambiar la definición de función, ya que esto es lo que realmente quiere nada:

private static Func<bool> MakeSynchroFunc<T>(IReader<IComposite> reader) where T : IComposite 

Es posible que tenga el parámetro T genérico para otras cosas, así que lo dejó allí.

+0

porque necesito el parámetro T para otra cosa, esto fue solo un ejemplo, no el código real. y me gustaría dejar que el compilador infiera el tipo de T en lugar de tener que especificarlo explícitamente. –

Cuestiones relacionadas