2013-05-27 8 views
5

Non pensare che il titolo possa spiegare di cosa sto parlando ed è un po 'difficile da spiegare, quindi lascerò che il codice parli. Puoi copiare e incollare questo in LINQPad ed eseguirlo come programma C#, o apportare le modifiche necessarie come un normale progetto C# in Visual Studio (ad esempio: cambia le chiamate a Dump() su Console.Writeline() ecc.) -L'oggetto generico ha bisogno di un cast anche se implementa l'interfaccia richiesta

Nota che se disattivi la riga nel metodo doStuff, non verrà compilata.

La mia domanda è: perché ho bisogno del cast quando generico2 implementa già Iab<TA,TB>? Questa è una cosa di covarianza? Sono ancora su .NET 3.5.

void Main() 
{ 
    doStuff<a,b>(); 
} 

public void doStuff<TA, TB>() 
where TA : class, Ia, new() 
where TB : class, Ib, new() 
{ 
    Iab<TA, TB> x = null; 

    x = new generic1<TA, TB>(); 
    x.Go().Dump(); 

    //x = new generic2<TA>(); // <-Cannot implicitly convert type 'UserQuery.generic2<TA>' to 'UserQuery.Iab<TA,TB>'. An explicit conversion exists (are you missing a cast?) 
    x = (Iab<TA, TB>) new generic2<TA>(); 
    x.Go().Dump(); 
} 

public interface Ia 
{} 

public interface Ib 
{} 

public class a : Ia 
{} 

public class b : Ib 
{} 

public interface Iab<TA,TB> 
where TA : class, Ia, new() 
where TB : class, Ib, new() 
{ 
    string Go(); 
} 

public class generic1<TA, TB> : Iab<TA,TB> 
where TA : class, Ia, new() 
where TB : class, Ib, new() 
{ 
    public string Go() 
    { 
     return "generic Base called"; 
    } 
} 

public class generic2<TA> : Iab<TA,b> 
where TA : class, Ia, new() 
{ 
public string Go() 
    { 
     return "generic Sub called"; 
    } 
} 

risposta

4

Credo che questo sia perché otterrete sempre quell'errore quando uno o più dei tipi (in questo caso, TS) non è noto al momento della compilazione.

Il compilatore non può garantire che doStuff() venga chiamato con tipi compatibili, quindi obbliga a trasmettere.

capire perché il compilatore non può fare questo, provare a chiamare doStuff() come segue:

public class X: b {} 

... 

doStuff<a, X>(); // Compiles ok but: 

Eccezione non gestita: System.InvalidCastException: Impossibile eseguire il cast oggetto di tipo 'generic2 1[Demo.Program+X]' to type 'Iab 2 [Demo. Programma + X, Demo.Program + Y]'.

Quindi è possibile chiamarlo con tipi che lo faranno schiantare; il compilatore non ti permetterà di farlo in silenzio.

+0

Ah, sì, certo. Quello che mi mancava :) Grazie! –

Problemi correlati