2012-04-18 19 views
5

para evitar la confusión que resumió algunas código:¿Cómo implementar el polimorfismo genérico en C#?

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main() 
     { 
      IManager<ISpecificEntity> specificManager = new SpecificEntityManager(); 
      IManager<IIdentifier> manager = (IManager<IIdentifier>) specificManager; 
      manager.DoStuffWith(new SpecificEntity()); 
     } 
    } 

    internal interface IIdentifier 
    { 
    } 

    internal interface ISpecificEntity : IIdentifier 
    { 
    } 

    internal class SpecificEntity : ISpecificEntity 
    { 
    } 

    internal interface IManager<TIdentifier> where TIdentifier : IIdentifier 
    { 
     void DoStuffWith(TIdentifier entity); 
    } 

    internal class SpecificEntityManager : IManager<ISpecificEntity> 
    { 
     public void DoStuffWith(ISpecificEntity specificEntity) 
     { 
     } 
    } 
} 

Cuando puedo depurar el código me sale un InvalidCastException en Main().

Sé que ISpecificEntity implementa IIdentifier. Pero, obviamente, un lanzamiento directo de IManager<ISpecificEntity> en un IManager<IIdentifier> no funciona.

Pensé que trabajar con la covarianza podría hacer el truco, pero cambiar IManager<TIdentifier> en IManager<in TIdentifier> tampoco ayuda.

Entonces, ¿hay alguna forma de convertir specificManager en IManager<IIdentifier>?

Gracias y todo lo mejor.

+0

por favor, lea: http://stackoverflow.com/questions/245607/how-is-generic-covariance-contra-variance-implemented-in-c-sharp-4-0 –

Respuesta

7

Con IManager<IIdentifier> que puede hacer tal cosa:

IIdentifier entity = new NotSpecificEntity(); 
manager.DoStuffWith(entity); 

que llevará a excepción, en su SpecificEntityManager, ya que sólo acepta parámetros de tipo ISpecificEntity

ACTUALIZACIÓN: Puede leer más acerca de covarianza y contravarianza en C# en Eric Lippert's blog

+0

... y es por eso que no es No se permite hacer lo que OP quiere hacer. +1 –

+0

@DanielHilgarth exactamente :) –

+0

Pero 'ISpecificEntity' implementa' IIdentifier'. Y 'TIdentifier' en' IManager' acepta solo 'IIdentifier'. Entonces, no debería haber una excepción en esa línea. ¿Me equivoco? – Palama

2

¿Por qué no?

ISpecificEntity bankAccountManager = new SpecificEntity(); 
IManager<IIdentifier> manager = (IManager<IIdentifier>)bankAccountManager; 
manager.DoStuffWith(new SpecificEntity()); 

?

+0

Porque 'SpecificEntity' no es un' IManager 'sino un' IIdentifier'. – Palama