Der folgende Code hat eine statische Methode Foo()
, die eine Instanzmethode aufruft Bar()
:
public sealed class Example
{
int count;
public static void Foo( dynamic x )
{
Bar(x);
}
void Bar( dynamic x )
{
count++;
}
}
Es wird ohne Fehler kompiliert *, generiert jedoch zur Laufzeit eine Laufzeitbinder-Ausnahme. Das Entfernen des dynamischen Parameters zu diesen Methoden führt erwartungsgemäß zu einem Compilerfehler.
Warum kann der Code mit einem dynamischen Parameter kompiliert werden? ReSharper zeigt es auch nicht als Fehler an.
Bearbeiten Sie 1: * in Visual Studio 2008
Bearbeiten 2: hinzugefügt, sealed
da es möglich ist, dass eine Unterklasse eine statische Bar(...)
Methode enthält. Selbst die versiegelte Version wird kompiliert, wenn es nicht möglich ist, dass zur Laufzeit eine andere Methode als die Instanzmethode aufgerufen wird.
c#
visual-studio-2008
dynamic
compiler-errors
Mike Scott
quelle
quelle
dynamic
sei denn, Sie müssen es wirklich.Antworten:
UPDATE: Die folgende Antwort wurde 2012 vor der Einführung von C # 7.3 (Mai 2018) verfasst . In Was ist neu in C # 7.3 , Abschnitt Verbesserte Überlastungskandidaten , Punkt 1, wird erläutert, wie sich die Regeln für die Überlastungsauflösung geändert haben, sodass nicht statische Überladungen vorzeitig verworfen werden. Die folgende Antwort (und diese ganze Frage) hat also mittlerweile meist nur noch historisches Interesse!
(Vor C # 7.3 :)
Aus irgendeinem Grund findet die Überlastungsauflösung immer die beste Übereinstimmung, bevor nach statischen und nicht statischen Werten gesucht wird. Bitte versuchen Sie diesen Code mit allen statischen Typen:
Dies wird nicht kompiliert, da die beste Überlastung diejenige ist, die a nimmt
string
. Aber hey, das ist eine Instanzmethode, also beschwert sich der Compiler (anstatt die zweitbeste Überladung zu nehmen).Ergänzung: Ich denke, die Erklärung für das
dynamic
Beispiel der ursprünglichen Frage lautet, dass wir, um konsistent zu sein, bei dynamischen Typen auch zuerst die beste Überlastung finden (nur Parameternummer und Parametertypen usw. prüfen, nicht statisch oder nicht -static) und erst dann auf statische Aufladung prüfen. Das bedeutet aber, dass die statische Prüfung bis zur Laufzeit warten muss. Daher das beobachtete Verhalten.Später Zusatz: Einige Hintergrundinformationen darüber, warum sie sich für diese lustige Reihenfolge entschieden haben, können diesem Blog-Beitrag von Eric Lippert entnommen werden .
quelle
dynamic
die Designer von C # , als es in die Sprache eingeführt wurde, gesagt: "Wir werden (2) Kompilierungszeit nicht berücksichtigen, wenn es sich um einendynamic
Ausdruck handelt." Mein Ziel hier ist es, eine Idee zu finden, warum sie sich entschieden haben, erst zur Laufzeit nach statischen oder instanziellen Daten zu suchen. Ich würde sagen, diese Überprüfung erfolgt zum Zeitpunkt der Bindung .Foo hat einen Parameter "x", der dynamisch ist, was bedeutet, dass Bar (x) ein dynamischer Ausdruck ist.
Es wäre durchaus möglich, dass Example Methoden wie:
In diesem Fall würde die richtige Methode aufgelöst, sodass die Anweisung Bar (x) vollkommen gültig ist. Die Tatsache, dass es eine Instanzmethode Bar (x) gibt, spielt keine Rolle und wird nicht einmal berücksichtigt: Da Bar (x) ein dynamischer Ausdruck ist, haben wir per Definition die Auflösung auf die Laufzeit verschoben.
quelle
Der "dynamische" Ausdruck wird zur Laufzeit gebunden. Wenn Sie also eine statische Methode mit der richtigen Signatur oder eine Instanzmethode definieren, überprüft der Compiler diese nicht.
Die "richtige" Methode wird zur Laufzeit festgelegt. Der Compiler kann nicht wissen, ob dort zur Laufzeit eine gültige Methode vorhanden ist.
Das Schlüsselwort "dynamic" ist für dynamische Sprachen und Skriptsprachen definiert, in denen die Methode jederzeit definiert werden kann, auch zur Laufzeit. Verrücktes Zeug
Hier befindet sich ein Beispiel für die Instanz, das Ints, aber keine Zeichenfolgen verarbeitet.
Sie können eine Methode hinzufügen, um alle "falschen" Aufrufe zu verarbeiten, die nicht verarbeitet werden konnten
quelle