C# - Type Conversion Error Obwohl Generische Einschränkung
-
06-07-2019 - |
Frage
Warum, mit einer generische Einschränkung auf den Typ-parameter T der Klasse P des "müssen Erben", der erste Aufruf erfolgreich, aber der zweite Aufruf fehl mit dem Typ-Konvertierung Fehler detailliert in den Kommentar:
abstract class A { }
static class S
{
public static void DoFirst(A argument) { }
public static void DoSecond(ICollection<A> argument) { }
}
static class P<T>
where T : A, new()
{
static void Do()
{
S.DoFirst(new T()); // this call is OK
S.DoSecond(new List<T>()); // this call won't compile with:
/* cannot convert from 'System.Collections.Generic.List<T>'
to 'System.Collections.Generic.ICollection<A>' */
}
}
Sollte nicht die generische Einschränkung sicherstellen, dass List<T>
ist ja ICollection<A>
?
Lösung
Dies ist ein Beispiel für C # 's Mangel an Kovarianz auf generische Typen (C # hat Unterstützung Matrixkovarianz). C # 4 wird diese Funktion auf Schnittstellentypen hinzufügen und auch mehrere BCL Schnittstellentypen aktualisieren und zu unterstützen.
Bitte finden Sie unter C # 4.0: Kovarianz und Kontra :
In diesem Artikel werde ich versuchen, einen decken die C # 4.0 Innovationen. Einer der Neu ist Kovarianz und Kontra auf Typ Parameter, die werden nun von generisch Delegierten unterstützt und generische Schnittstellen. Lassen Sie uns zunächst was tut diese Worte bedeuten:)
Andere Tipps
Die Einschränkung hat keine Auswirkung auf das Problem; das Problem ist, dass Sie eine Liste in einem Parameter sind vorbei, die ICollection erfordert - C # nicht Kovarianz unterstützen, so müssen Sie explizit die Liste in eine ICollection-Stimmen:
S.DoSecond((ICollection<A>) new List<T>()); // this call will be happy
Sie haben eine stark typisierte parameter für DoSecond als Typ ICollection<A>.Trotz der Tatsache, dass T ist vom Typ A, zur compile-Zeit gibt es keine implizite cast zwischen Liste<T> und ICollection<A>.Sie müssen entweder die Liste erstellen, und cast es zu die ICollection-Schnittstelle<A> , wenn Sie anrufen DoSecond, oder machen DoSecond eine generische Methode selbst.
HINWEIS:Diese Art der implizite cast sollte unterstützt werden, die in C# 4.0, die eine deutlich höhere co/Kontravarianz über das, was in C# 3.0 bietet.