2013-05-27 20 views
5

Nie sądzę, że tytuł może wyjaśnić, o co mi chodzi, i jest to nieco trudne do wyjaśnienia, więc pozwolę, aby kod mówił. Możesz skopiować i wkleić to do LINQPada i uruchomić jako program C# lub wprowadzić niezbędne korekty jako zwykły projekt C# w wizualnym studio (np. Zmienić wywołanie na Dump() na Console.Writeline() itp.) -Obiekt ogólny wymaga rzutowania, mimo że implementuje wymagany interfejs.

Należy zauważyć, że jeśli odkomentujesz linię w metodzie DoStuff, nie zostanie ona skompilowana.

Moje pytanie brzmi: dlaczego potrzebuję rzutowania, gdy generic2 już implementuje Iab<TA,TB>? Czy to jest coś z kowariancji? Nadal jestem na .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"; 
    } 
} 

Odpowiedz

4

wierzę, to dlatego, że zawsze możesz dostać ten błąd, gdy jeden lub więcej typów (w tym przypadku TS) nie jest znany w czasie kompilacji.

Kompilator nie może zagwarantować, że doStuff() zostanie wywołany z kompatybilnymi typami, więc zmusza do rzucenia.

Aby zrozumieć, dlaczego kompilator nie może tego zrobić, spróbuj dzwoniąc doStuff() następująco:

public class X: b {} 

... 

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

nieobsługiwany wyjątek: System.InvalidCastException: Nie można rzutować obiektu typu „generic2 1[Demo.Program+X]' to type 'Iab 2 [Demo. Program + X, Demo.Program + Y] ".

Można go nazwać typami, które powodują awarię; kompilator nie pozwoli ci tego cicho.

+0

Ah, tak, oczywiście. Tęsknię za tym :) Dzięki! –

Powiązane problemy