Erweiterungsmethode und dynamisches Objekt

96

Ich werde mein Problem im folgenden Code-Snippet zusammenfassen.

List<int> list = new List<int>() { 5, 56, 2, 4, 63, 2 };
Console.WriteLine(list.First());

Der obige Code funktioniert einwandfrei.

Jetzt habe ich folgendes versucht

dynamic dList = list;
 Console.WriteLine(dList.First());

aber ich bekomme RuntimeBinderException. Warum ist es so?

Santosh Singh
quelle
Dies scheint ein Duplikat dieser Frage zu sein, die erst vor 4 Tagen gestellt wurde. Stackoverflow.com/questions/5270782/…
jbtule
@jbtule Der Unterschied ist, dass das thishier dynamisch ist, aber wenn Sie hier landen, sollten Sie sich wahrscheinlich auch diese Frage
ansehen

Antworten:

130

Um die Antwort von Stecya zu erweitern ... Erweiterungsmethoden werden durch dynamische Typisierung in Form von Erweiterungsmethoden nicht unterstützt , dh als Instanzmethoden bezeichnet. Dies wird jedoch funktionieren:

dynamic dList = list;
Console.WriteLine(Enumerable.First(dList));

Das kann natürlich nützlich sein oder auch nicht. Wenn Sie weitere Informationen darüber geben könnten, warum und wie Sie versuchen, dynamisches Schreiben zu verwenden, können wir Ihnen möglicherweise weiterhelfen.

Jon Skeet
quelle
Ich habe mit dynamischen Objekten gespielt und diese Ausnahme erhalten. Haben Sie einen Artikel zu diesem Thema geschrieben, in dem Sie dynamische Objekte verwenden oder nicht verwenden können
Santosh Singh
19
@geek: Persönlich ist meine Faustregel, nur dort zu verwenden, dynamicwo Sie es wirklich brauchen ... Wenn Sie sonst mit Reflexion auf Mitglieder zugreifen würden, ist das ein großes Zeichen. Auf der anderen Seite bin ich ein eingefleischter statischer Typ - andere schlagen möglicherweise weniger pessimistische Richtlinien vor :)
Jon Skeet
2
Es ist möglicherweise besser lesbar, auf den bekannten Typ zurückzugreifen. Dies funktioniert: Console.WriteLine (((List <int>) dList) .First ()); Oder Console.WriteLine ((dList als Liste <int>) .First ());.
AVee
138

Um Jons Antwort zu erweitern, funktioniert dies nicht, weil bei regulären, nicht dynamischen Code-Erweiterungsmethoden alle dem Compiler bekannten Klassen nach einer statischen Klasse mit einer passenden Erweiterungsmethode durchsucht werden. Die Suche erfolgt in der Reihenfolge, in der die Verschachtelung des Namespaces und die verfügbaren usingAnweisungen in jedem Namespace basieren .

Das bedeutet , dass , um eine dynamische Erweiterung Methodenaufruf korrekt aufgelöst zu bekommen, irgendwie das DLR wissen , hat zur Laufzeit , was alle Namespace Verschachtelungen und usingRichtlinien wurden im Quellcode . Wir haben keinen Mechanismus zum Codieren all dieser Informationen in die Anrufstelle. Wir haben überlegt, einen solchen Mechanismus zu erfinden, aber festgestellt, dass er zu teuer ist und zu viel Zeitplanrisiko birgt, um ihn wert zu sein.

Eric Lippert
quelle
Vielen Dank für die Erklärung.
Santosh Singh
3
Ist eine solche Funktion in Sicht? Es wäre sicherlich eine bahnbrechende Veränderung; Aufrufe, die derzeit RunTimeBinderExceptions auslösen, funktionieren plötzlich beim erneuten Kompilieren der Quelle. Würden mit der Implementierung einer solchen Funktion auch Sicherheitsrisiken verbunden sein?
Ani
5
@ani: Planen wir die Implementierung dieser Funktion? Nein . Gibt es irgendwelche Sicherheitsrisiken? Mir sind keine bekannt; Welche Art von Sicherheitsrisiko hatten Sie im Sinn? Sagen Sie zunächst, wer der Angreifer ist und welche Bedrohung er für den Benutzer darstellt.
Eric Lippert
@EricLippert, ich habe verstanden, dass alle dynamicObjekte gleich C # sind: Es DynamicObjectgibt also keine Möglichkeit, sie zu unterscheiden, und ist einer der Gründe, warum es nicht möglich ist, Erweiterungsmethoden hinzuzufügen dynamic, stimmt das?
Tom Sarduy
@EricLippert erwägt, diese Antwort etwas weiter zu erweitern und einen Satz nach dem Motto "Wenn einer der Parameter dynamisch ist, werden alle Auflösungen bis zur Laufzeit verschoben " hinzuzufügen . Während es für Sie offensichtlich ist, dass dieses wichtige Bit auf SO nirgendwo anders zu finden ist (siehe zum Beispiel stackoverflow.com/questions/48324768 )
Alexei Levenkov
18

Weil First()ist keine Methode von List. Es ist in Linq Extension to definiertIEnumerable<>

Stecya
quelle