2012-04-18 7 views
5

um Verwirrung zu vermeiden zusammengefasst ich einige Code:Wie generischer Polymorphismus in C# zu implementieren?

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) 
     { 
     } 
    } 
} 

Wenn ich den Code debuggen erhalte ich eine InvalidCastException in Main().

Ich weiß, dass ISpecificEntityIIdentifier implementiert. Aber offensichtlich eine direkte Besetzung von IManager<ISpecificEntity> in eine IManager<IIdentifier> funktioniert nicht.

Ich dachte, die Arbeit mit Kovarianz könnte den Trick tun, aber in IManager<in TIdentifier> zu ändern hilft auch nicht.

So ist es eine Möglichkeit, specificManager in ein IManager<IIdentifier> wirft?

Danke und alles Gute.

+0

lesen Sie bitte: http://stackoverflow.com/questions/245607/how-isgeneric-covariance-contra-varianz-implementiert-in-c-sharp-4-0 –

Antwort

7

Mit IManager<IIdentifier> können Sie so etwas tun:

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

, die auf Ausnahme führen wird, in Ihrem SpecificEntityManager, weil es nur Parameter vom Typ akzeptiert ISpecificEntity

UPDATE: Sie können mehr über Kovarianz lesen und Kontravarianz in C# um Eric Lippert's blog

+0

... und deshalb ist es nicht Ich darf nicht tun, was das OP machen will. +1 –

+0

@DanielHilgarth genau :) –

+0

Aber 'ISpecificEntity' implementiert' Identifier'. Und "IDentifier" in "IManager" akzeptiert nur "Identifier". Also sollte es in dieser Zeile keine Ausnahme geben. Liege ich falsch? – Palama

2

Warum nicht:

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

?

+0

Weil 'SpecificEntity' kein' IManager 'ist, sondern ein' Identifier'. – Palama