C # Dynamics: Convert.ChangeType im Vergleich zu Cast

9

Könnte jemand erklären, warum das Umwandeln eines dynamischen Objekts als Klasse diese Klasse zurückgibt, während Convert.ChangeType ein dynamisches Objekt zurückgibt, insbesondere zur Laufzeit? Zum Beispiel:

%Vor%

Das umfassendere Problem: Ich habe eine Reihe von Hilfsklassen, die eine generische Schnittstelle implementieren. Ich muss eine Liste dieser Klassen an andere Objekte weitergeben; Die verschiedenen Hilfsklassen verwenden jedoch unterschiedliche Typen für den generischen Parameter. Daher kann ich eine Liste der Hilfsklassen nicht direkt übergeben:

%Vor%

Also dachte ich, ich könnte die Laufzeit vortäuschen, indem ich eine Container-Klasse erstelle, die die Hilfsklasse und den generischen Typ enthält, aber Dynamiken nutzt:

%Vor%

Jetzt kann ich eine Liste von ContainerClass erstellen und übergeben. Die gesamte Verarbeitung funktioniert großartig, bis ich die Ergebnisse von Foo () zurück zum Ziel IEnumerables zuordnen muss. Zu diesem Zeitpunkt erhalte ich Laufzeitfehler, die darauf hinweisen, dass der Typ Objekt nicht in diese und jene konkrete Klasse konvertiert werden kann, obwohl die ungepackten Objekttypen übereinstimmen diejenigen, die benötigt werden. Wenn ich eine ähnliche Syntax wie in dTest2 oben versuche, kann die Laufzeitumgebung die "Konvertierung" immer noch nicht herausfinden.

Ich verstehe, dass dies wahrscheinlich ein Missbrauch von dynamischer und schlechter Programmierpraxis ist. Ich werde sicherlich eine andere Lösung verwenden, wenn und wenn ich eine identifizieren kann, aber für den Moment muss ich entweder diese Arbeit machen oder mit etwas weniger Ambitioniertem gehen.

    
Stardew Jellyfeather 12.01.2014, 13:39
quelle

2 Antworten

8

Zur Ausführungszeit gibt es so etwas wie dynamic wirklich nicht.

Der Aufruf von Convert.ChangeType liefert jedoch einen dynamic -Wert als Argument. Jeder -Methodenaufruf, der ein dynamic -Argument verwendet, wird so behandelt, als hätte er einen Rückgabewert von dynamic , weil der Compiler nicht weiß, was die tatsächliche Signatur bis zur Ausführungszeit sein wird.

Wenn Sie jedoch eine Umwandlung, einen is - oder as -Ausdruck oder einen Konstruktoraufruf verwenden, gibt es nur den eins -Typ, der das Ergebnis sein kann - also der Typ des Ausdrucks .

Was Ihr breiteres Problem angeht - mir ist nicht klar, dass die Verwendung von dynamic Ihnen besonders helfen würde. Möglicherweise möchten Sie eine Basisschnittstelle für IHelper<T> deklarieren - eine nicht generische Schnittstelle, die nur für tatsächliche IHelper<T> Instanzen verwendet wird. Dann können Sie ein List<IHelper> haben, wobei jedes Element tatsächlich ist und für einige IHelper<T> ein T ist, wobei aber T von Instanz zu Instanz variiert. Die IHelper Schnittstelle ist nicht wirklich erforderlich hier, obwohl, wenn Ihre IHelper<T> Schnittstelle wirklich andere Mitglieder enthält, die T nicht verwenden, diese stattdessen zu IHelper verschoben werden könnten. Es kann jedoch nützlich sein, es nur aus Gründen der Klarheit zu verwenden.

Nun, wenn Sie eine bestimmte IHelper verwenden müssen, dann dynamische Typisierung könnte kurz nützlich sein. Sie können eine generische Methode deklarieren und die dynamische Typisierung das Typargument zur Ausführungszeit ermitteln lassen. Zum Beispiel:

%Vor%     
Jon Skeet 12.01.2014, 13:43
quelle
4

Basierend auf Jon Skeets Antwort denke ich, dass Sie etwas wirklich Interessantes tun können und das dynamische Keyword vermeiden können, da es sich auf die Leistung auswirkt.

Verwenden Sie IHelper<T> : IHelper . Jetzt können Sie die Helfer wie in einem List<IHelper> speichern. Jetzt könnten Sie die Foo-Methode aufrufen, indem Sie Typen zu einer generischen Methode umwandeln.

%Vor%

Hinweis: Sie können IEnumerable<SomeClass> in IEnumerable<object> und UseHelper<SomeClass> in UsehelperDelegate wegen Kovarianz und Kontravarianz .

Bearbeiten: Es stellt sich heraus, dass Sie tatsächlich eine neue konkrete Funktion aus dem generischen erstellen und zur Karte hinzufügen können. Auf diese Weise können Sie dynamic vermeiden.

%Vor%     
dburner 12.01.2014 14:36
quelle