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>?

War es hilfreich?

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top