2017-10-08 6 views
1

Ich habe ein seltsames Verhalten.Cast dynamisch durch externe statische Erweiterung Anruf bleibt dynamisch

Ich verwende die folgende Methode, um jedes Objekt auf einen beliebigen Typ zu übertragen.

using System.Dynamic; 

...

/// <summary> 
/// Casts any object to passed type. 
/// </summary> 
/// <typeparam name="T">Wished type</typeparam> 
/// <param name="obj">The object you want to be casted.</param> 
public static T ToType<T>(this object obj) => (T)obj; 

Zum Beispiel (Objekt dynamisch):

AnyLabel.Tag = new ExpandoObject(); 
AnyLabel.Tag.ToType<dynamic>().Item2 = new Form(); // works 

nun folgende Situation (dynamisch typisierte Objekt):

// var is NOT from type form, why?: 
var form = ToType<Form>(AnyLabel.Tag.ToType<dynamic>().Item2); 

// the other way works like desired: 
var form2 = ((Form)AnyLabel.Tag.ToType<dynamic>().Item2); 

I kann auf keine Formulareigenschaften/Methoden zugreifen, die den c verwenden asting Erweiterung à la:

ToType<Form>(AnyLabel.Tag.ToType<dynamic>().Item2).Show(); 

Meine Frage ist, warum ist das erste var nicht vom Typ Form und verweigert ich den letzten Code Teil auszuführen?

+0

Ihr Code konnte nicht kompiliert werden. Bitte senden Sie den kompilierbaren Code. –

+0

Verzeihung. Bearbeitet. – Bagerfahrer

+0

Warum definieren Sie eine Erweiterungsmethode, wenn Sie sie nicht als Erweiterungsmethode verwenden? – oerkelens

Antwort

1

Die Methode ToType<T>() könnte überladene Versionen haben. Wenn keine Dynamik beteiligt ist, löst der Compiler die richtige Überladung zur Kompilierungszeit auf. Ob; es ist jedoch eine Dynamik involviert, die Bindung findet zur Laufzeit statt, d. h. die rechte Überladung wird zur Laufzeit unter Verwendung des Laufzeittyps der Argumente bestimmt. Diese Überladungen können auch unterschiedliche Rückgabetypen haben. Da dieser Rückgabetyp zur Kompilierzeit nicht bekannt ist, entscheidet sich der C# -Compiler dafür, dynamic als Rückgabetyp Ihrer Funktion zu wählen.

Nun könnten Sie davon ausgehen, dass Sie keine überladene Version haben und dass Form sicher angenommen werden kann. Aber was passiert, wenn Sie später Überladungen hinzufügen? Sollte dies plötzlich den Rückgabetyp eines Ausdrucks ändern, der sich nicht geändert hat? Das Hinzufügen einer Überladung würde zu einer Änderung des vorhandenen Codes führen, der zum Zeitpunkt der Kompilierung nicht erkannt werden kann.


Welche Art Rückkehr zur Compile-Zeit zu wählen, wenn Überlastung durch Laufzeit Argument Typ bestimmt wird?

public static T ToType<T>(this object obj) => (T)obj; 
public static int ToType<T>(this int i) => i; // Makes no sense, but valid code. 
public static dynamic ToType<T>(this dynamic d) => d; // Valid as well. 
+0

Nachdem ich 10 Mal gelesen habe, habe ich es verstanden. Also war mein Irrtum, nur an das erwartete Ergebnis zu denken. Vielen Dank! – Bagerfahrer

+0

Überladungsauflösung kann Ihre Nudeln backen. –

+0

Sie könnten auf der Basis Ihrer großen Antwort die Lösung hinzufügen: 'ToType

((Objekt) AnyLabel.Tag.ToType () .Item2) .Show();' Dies gibt an, auf welche Überladung ich verweisen möchte. Dies würde Ihre Antwort abrunden und allen helfen, die das finden. – Bagerfahrer