Frage Der Delegat kann nicht in einen allgemeinen Typ T umgewandelt werden


Warum können wir nicht eine Instanz von delegieren zu einem generischen Typ T?

Betrachten Sie eine Hilfsmethode CreateDelegate das schafft eine Instanz von T, die a ist delegieren, d. h. ein Typ, der abgeleitet ist von MulticastDelegate.

 T CreateDelegate<T>() {… }

Leider erlauben Generika keine Einschränkung T zu einem Typ von abgeleitet MulticastDelegate gibt folgenden Kompilierungsfehler:

Constraint kann keine spezielle Klasse 'System.MulticastDelegate' sein

Trotzdem überprüft diese Hilfsmethode das T ist kompatibel mit MulticastDelegate und Erstellen eines Delegierten über Reflection through Delegate::CreateDelegate. Aber wenn wir versuchen, das Ergebnis von Delegate::CreateDelegate zu T, erhalten wir den folgenden Kompilierungsfehler:

Der Typ 'System.Delegate' kann nicht in 'T' konvertiert werden

Allerdings, wenn ich es zuerst anwende object und dann zu T es wird gut funktionieren:

T h = (T) ((object) Delegate.CreateDelegate(typeof(T), target, m));

Warum können wir den Delegaten nicht direkt auf T übertragen?


6
2018-02-10 17:09


Ursprung


Antworten:


Die C # -Sprache erzwingt eine statische Überprüfung, ob eine Umwandlung vom Typ X in den Typ Y gültig ist - d. H. Ob sie erfolgt Sinn dass der Compiler (zu einem gewissen Grad) die Kompatibilität garantieren und Fehler ablehnen kann, die während der Kompilierungszeit gelöscht werden. Ein unbeschränkter generischer Typ T und System.Delegate habe nichts direkt gemeinsam. Wie auch immer, wenn es zu object der Compiler weiß das jeden Typ ist im Wesentlichen ein object, so erlaubt es die Besetzung. Das bedeutet nicht, dass eine Laufzeittypprüfung in einem bestimmten Fall nicht fehlschlägt.

Das as Der Operator ist etwas toleranter, da er keine Ausnahme für einen ansonsten ungültigen Cast darstellt. Der Compiler ist auch weniger streng bei der Anwendung statischer Prüfungen. In Ihrem speziellen Fall ist dies hilfreich, da Sie die Zwischenform weglassen können object und benutzen as T. Allerdings ist dies erforderlich as arbeitet nur mit Klassentypen, Sie müssen also die where T : class Zwang.

Die Methode würde dann so aussehen (vereinfacht):

public T CreateDelegate<T>(…) where T : class
{
    return Delegate.CreateDelegate(typeof(T), …) as T;
}

Wie von @usr vorgeschlagen, ist eine empfohlene Lektüre Eric Lipperts Blog, z. Dieser Artikel zu Güssen und Typparametern.


10
2018-02-10 17:15