2012-04-18 15 views
5

per evitare confusione ho riassunto po 'di codice:Come implementare il polimorfismo generico in 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) 
     { 
     } 
    } 
} 

Quando il debug del codice ottengo un InvalidCastException in Main().

So che ISpecificEntity implementa IIdentifier. Ma ovviamente un cast diretto da IManager<ISpecificEntity> in un IManager<IIdentifier> non funziona.

Ho pensato che lavorare con la covarianza poteva fare il trucco ma cambiare IManager<TIdentifier> in IManager<in TIdentifier> non aiuta neanche.

Quindi, c'è un modo per trasmettere specificManager in un IManager<IIdentifier>?

Grazie e tutto il meglio.

+0

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

risposta

7

Con IManager<IIdentifier> si può fare una cosa:

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

Questo porterà ad eccezione, nella vostra SpecificEntityManager, perché accetta solo i parametri di tipo ISpecificEntity

UPDATE: Si può leggere di più su di covarianza e controvarianza in C# a Eric Lippert's blog

+0

... ed è per questo che non è Non è permesso fare ciò che l'OP vuole fare. +1 –

+0

@DanielHilgarth esattamente :) –

+0

Ma 'ISpecificEntity' implementa' IIdentificatore'. E 'TIdentifier' in' IManager' accetta solo 'IIdentificatore'. Quindi, non ci dovrebbe essere un'eccezione in quella linea. Ho sbagliato? – Palama

2

Perché non:

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

?

+0

Perché 'SpecificEntity' non è un 'IManager ' ma un 'IIdentificatore'. – Palama