Frühe und späte Bindung

81

Ich versuche, meinen Kopf herumzukriegen, wenn in C # eine frühe / späte Bindung auftritt.

Nicht virtuelle Methoden sind immer früh gebunden. Virtuelle Methoden sind immer spät gebunden: Der Compiler fügt zusätzlichen Code ein, um die tatsächliche Methode aufzulösen, an die zur Ausführungszeit gebunden werden soll, und prüft die Typensicherheit. Der Subtyp-Polymorphismus verwendet also eine späte Bindung.

Das Aufrufen von Methoden unter Verwendung von Reflexion ist ein Beispiel für eine späte Bindung. Wir schreiben den Code, um dies zu erreichen, im Gegensatz zum Compiler. (ZB Aufruf von COM-Komponenten.)

VB.NET unterstützt implizite späte Bindung, wenn Option Strict deaktiviert ist. Ein Objekt wird spät gebunden, wenn es einer Variablen zugewiesen wird, die als vom Typ Objekt deklariert ist. Der VB-Compiler fügt Code ein, um zur Ausführungszeit an die richtige Methode zu binden und ungültige Aufrufe abzufangen. C # unterstützt diese Funktion nicht.

Gehe ich in die richtige Richtung?

Was ist mit dem Aufrufen von Delegaten und dem Aufrufen einer Methode über eine Schnittstellenreferenz? Ist das früh oder spät bindend?

Cybermaxs
quelle

Antworten:

101

In C # ist alles früh gebunden, es sei denn, Sie gehen über die Reflection-Oberfläche.

Frühe Bindung bedeutet nur, dass die Zielmethode zur Kompilierungszeit gefunden wird und Code erstellt wird, der dies aufruft. Ob es virtuell ist oder nicht (was bedeutet, dass es einen zusätzlichen Schritt gibt, um es zum Zeitpunkt des Anrufs zu finden, ist irrelevant). Wenn die Methode nicht vorhanden ist, kann der Compiler den Code nicht kompilieren.

Spät gebunden bedeutet, dass die Zielmethode zur Laufzeit nachgeschlagen wird. Oft wird der Textname der Methode verwendet, um sie nachzuschlagen. Wenn die Methode nicht da ist, knall. Das Programm stürzt zur Laufzeit ab oder wechselt in ein Ausnahmebehandlungsschema.

Die meisten Skriptsprachen verwenden eine späte Bindung, und kompilierte Sprachen verwenden eine frühe Bindung.

C # (vor Version 4) bindet nicht zu spät. Sie können jedoch die Reflection-API verwenden, um dies zu tun. Diese API wird zu Code kompiliert, der nach Funktionsnamen sucht, indem sie zur Laufzeit in Assemblys durchsucht wird. VB kann spät binden, wenn Option Strict deaktiviert ist.

Die Bindung wirkt sich normalerweise auf die Leistung aus. Da für die späte Bindung zur Laufzeit nachgeschlagen werden muss, bedeutet dies normalerweise, dass Methodenaufrufe langsamer sind als früh gebundene Methodenaufrufe.


Für eine normale Funktion kann der Compiler die numerische Position im Speicher ermitteln. Wenn die Funktion aufgerufen wird, kann sie eine Anweisung zum Aufrufen der Funktion an dieser Adresse generieren.

Für ein Objekt mit virtuellen Methoden generiert der Compiler eine V-Tabelle. Dies ist im Wesentlichen ein Array, das die Adressen der virtuellen Methoden enthält. Jedes Objekt mit einer virtuellen Methode enthält ein verstecktes Element, das vom Compiler generiert wird und die Adresse der V-Tabelle ist. Wenn eine virtuelle Funktion aufgerufen wird, ermittelt der Compiler die Position der entsprechenden Methode in der V-Tabelle. Es wird dann Code generiert, um in die v-Tabelle der Objekte zu schauen und die virtuelle Methode an dieser Position aufzurufen.

Es gibt also eine Suche für die virtuelle Funktion. Dies ist stark optimiert, so dass es zur Laufzeit sehr schnell gehen wird.

Früh gebunden

  • Der Compiler kann herausfinden, wo sich die aufgerufene Funktion zur Kompilierungszeit befindet.
  • Der Compiler kann frühzeitig (bevor der Programmcode ausgeführt wird) garantieren, dass die Funktion vorhanden und zur Laufzeit aufrufbar ist.
  • Der Compiler garantiert, dass die Funktion die richtige Anzahl von Argumenten akzeptiert und vom richtigen Typ ist. Außerdem wird überprüft, ob der Rückgabewert vom richtigen Typ ist.

Spätbindung

  • Die Suche dauert länger, da es sich nicht um eine einfache Versatzberechnung handelt. In der Regel müssen Textvergleiche durchgeführt werden.
  • Die Zielfunktion ist möglicherweise nicht vorhanden.
  • Die Zielfunktion akzeptiert möglicherweise die an sie übergebenen Argumente nicht und hat möglicherweise einen Rückgabewert vom falschen Typ.
  • Bei einigen Implementierungen kann sich die Zielmethode zur Laufzeit tatsächlich ändern. Die Suche kann also eine andere Funktion ausführen. Ich denke, dies geschieht in der Ruby-Sprache. Sie können eine neue Methode für ein Objekt definieren, während das Programm ausgeführt wird. Durch die späte Bindung können Funktionsaufrufe eine neue Überschreibung für eine Methode aufrufen, anstatt die vorhandene Basismethode aufzurufen.
Scott Langham
quelle
Ich denke, Sie wollten sagen "Die VB-Sprache selbst bindet nicht zu spät ..."
Michael Meadows
Eigentlich benutze ich kein VB ... also weiß ich nicht viel darüber. Ich meinte C #, aber es sieht so aus, als würde ich mich nur wiederholen. Ich würde mir allerdings vorstellen, dass Sie Recht haben, also werde ich es reparieren!
Scott Langham
21
Dynamische Typisierung ist nicht dasselbe wie spätes Binden. Der Unterschied ist subtil, aber wichtig. Die späte Bindung bindet immer noch an einen Typ, dies geschieht nur zur Laufzeit. Die dynamische Eingabe ist nicht bindend. Stattdessen werden Mitgliedsinformationen zur Laufzeit unabhängig vom Typ aufgelöst.
Michael Meadows
1
" Für ein Objekt mit virtuellen Methoden generiert der Compiler eine V-Tabelle. " Das ist ein bisschen falsch - "Klasse", nicht "Objekt".
Turdus-Merula
1
@ IvanRuski Das glaube ich nicht. Zur Kompilierungszeit sind alle Argumenttypen bekannt, die ein Delegat akzeptiert. Daher kann der Compiler zur Kompilierungszeit (die "früh" ist) und nicht zur Laufzeit (die "spät" ist) garantieren, dass der Aufruf funktioniert.
Scott Langham
18

C # 3 verwendet eine frühe Bindung.

C # 4 fügt dem dynamicSchlüsselwort eine späte Bindung hinzu . Weitere Informationen finden Sie im Blogeintrag von Chris Burrow zu diesem Thema.

Bei virtuellen und nicht virtuellen Methoden ist dies ein anderes Problem. Wenn ich aufrufe string.ToString(), ist der C # -Code an die virtuelle object.ToString()Methode gebunden . Der Code des Aufrufers ändert sich nicht je nach Objekttyp. Virtuelle Methoden werden vielmehr über eine Tabelle von Funktionszeigern aufgerufen. Eine Objektinstanz bezieht sich auf die Tabelle des Objekts, die auf seine ToString()Methode zeigt. Bei einer Zeichenfolgeninstanz zeigt die virtuelle Methodentabelle auf die ToString()Methode. Ja, das ist Polymorphismus. aber es ist nicht spät bindend.

Joe Erickson
quelle
1
Ich stimme dieser Erklärung nicht ganz zu. Wenn Sie in C # eine Instanzmethode oder ein Instanzfeld als vom virtuellen Mittel abgeleiteten Typ markieren, kann dies die Implementierung des Basistyps in der Vererbungskette überschreiben. Bei virtuellen Methoden weiß die CLR anhand der Laufzeitobjektinstanz, welche Methode zur Laufzeit aufgerufen werden soll. Wahrscheinlich stimme ich Ihnen nur zu, dass es sich um eine Implementierung des Polymorphismus handelt. Dann sorgen Sie für Verwirrung, indem Sie sagen, dass es nicht zu spät bindend ist. Es ist eine späte Bindung, da CLR die korrekte Implementierung des Laufzeittyps nur aufrufen kann, wenn es den Laufzeittyp der Objektinstanz kennt.
Julius Depulla
5

In den meisten Fällen ist eine frühzeitige Bindung das, was wir täglich tun. Wenn beispielsweise Employeezur Kompilierungszeit eine Klasse verfügbar ist, erstellen wir einfach die Instanz dieser Klasse und rufen alle Instanzmitglieder auf. Dies ist eine frühe Bindung.

//Early Binding
**Employee** employeeObject = new **Employee**();
employeeObject.CalculateSalary();

Wenn Sie jedoch zur Kompilierungszeit nicht über die Kenntnisse der Klasse verfügen, besteht die einzige Möglichkeit darin, die Bindung mithilfe von Reflexion zu spät zu binden. Ich bin auf ein ausgezeichnetes Video gestoßen, das diese Konzepte erklärt - hier ist der Link .

Prasad
quelle
3

Es ist ein sehr alter Beitrag, wollte aber weitere Informationen hinzufügen. Die späte Bindung wird verwendet, wenn Sie das Objekt zur Kompilierungszeit nicht instanziieren möchten. In verwenden C#Sie Activator, um bind object zur Laufzeit aufzurufen.

Kumar Nitesh
quelle
3

Frühe Bindung

Der Name selbst beschreibt, dass der Compiler weiß, um welche Art von Objekt es sich handelt, welche Methoden und Eigenschaften er enthält. Sobald Sie das Objekt deklariert haben, füllt .NET Intellisense seine Methoden und Eigenschaften mit einem Klick auf die Punktschaltfläche.

Häufige Beispiele:

ComboBox cboItems;

ListBox lstItems; Wenn wir in den obigen Beispielen das cboItem eingeben und einen Punkt gefolgt von platzieren, werden automatisch alle Methoden, Ereignisse und Eigenschaften eines Kombinationsfelds ausgefüllt, da der Compiler bereits weiß, dass es sich um eine Combobox handelt.

Späte Bindung

Der Name selbst beschreibt, dass der Compiler nicht weiß, um welche Art von Objekt es sich handelt, welche Methoden und Eigenschaften er enthält. Sie müssen es als Objekt deklarieren. Später müssen Sie den Typ des Objekts und die darin gespeicherten Methoden abrufen. Alles wird zur Laufzeit bekannt sein.

Häufige Beispiele:

Objektobjekte;

objItems = CreateObject ("DLL- oder Assemblyname"); Hier wird während der Kompilierungszeit die Art der Objekte nicht bestimmt. Wir erstellen ein Objekt einer DLL und weisen es den Objekten zu, damit alles zur Laufzeit bestimmt wird.

Frühe Bindung vs. späte Bindung

Kommen wir jetzt ins Bild ...

Die Anwendung wird beim frühen Binden schneller ausgeführt, da hier kein Boxen oder Entpacken erfolgt.

Einfacher, den Code in Early Binding zu schreiben, da der Intellisense automatisch ausgefüllt wird

Minimale Fehler bei der frühen Bindung, da die Syntax während der Kompilierungszeit selbst überprüft wird.

Eine späte Bindung würde in allen Arten von Versionen unterstützt, da alles zur Laufzeit entschieden wird.

Minimale Auswirkung von Code bei zukünftigen Verbesserungen, wenn die späte Bindung verwendet wird.

Leistung wird Code in der frühen Bindung sein. Beide haben Vor- und Nachteile. Es ist die Entscheidung des Entwicklers, die geeignete Bindung basierend auf dem Szenario auszuwählen.

RajGanesh
quelle
2

In sehr einfachen Worten, die frühe Bindung erfolgt zur Kompilierungszeit und der Compiler verfügt über Kenntnisse über den Typ und alle seine Mitglieder. Die späte Bindung erfolgt zur Laufzeit. Der Compiler weiß nichts über den Typ und seine Mitglieder. Ich bin auf youtube auf ein exzellentes Video gestoßen, das diese Konzepte erklärt.

http://www.youtube.com/watch?v=s0eIgl5iqqQ&list=PLAC325451207E3105&index=55&feature=plpp_video

http://www.youtube.com/playlist?list=PLAC325451207E3105

Suresh
quelle
1

Dieser Artikel ist eine Anleitung zum Erstellen einer .net-Komponente, deren Verwendung in einem Vb6-Projekt zur Laufzeit mithilfe einer späten Bindung, Anhängen der Ereignisse und Abrufen eines Rückrufs.

http://www.codeproject.com/KB/cs/csapivb6callback2.aspx

Dieser Artikel ist eine Anleitung zum Erstellen und Verwenden einer .NET-Komponente in einem VB6-Projekt. Es gibt viele Beispiele zu diesem Thema. Warum habe ich ein neues geschrieben? Meiner bescheidenen Meinung nach besteht in anderen Artikeln der fehlende Teil darin, das Ereignis zur Laufzeit anzuhängen. In diesem Artikel erstellen wir eine .NET-Komponente, markieren sie als sichtbare COM-Komponente, verwenden sie zur Laufzeit in VB6 und hängen sie an ihre Ereignisse an.

https://www.codeproject.com/Articles/37127/Internet-Explorer-Late-Binding-Automation

Die meisten Entwickler benötigen häufig die Internet Explorer-Automatisierung. Dies bedeutet im Wesentlichen, dass ein Browser geöffnet, einige Formulare ausgefüllt und Daten programmgesteuert veröffentlicht werden.

Am häufigsten werden shdocvw.dll (das Microsoft-Webbrowser-Steuerelement) und Mshtml.dll (die HTML-Analyse- und Rendering-Komponente) oder Microsoft.Mshtml.dll verwendet, bei denen es sich tatsächlich um einen .NET-Wrapper für Mshtml.dll handelt. Weitere Informationen zu Internet Explorer - Über den Browser erhalten Sie hier.

Wenn Sie die obige Methode und die DLLs auswählen, sehen wir uns einige der Probleme an, mit denen Sie möglicherweise zu kämpfen haben:

Sie müssen diese DLLs verteilen, da Ihr Projekt von diesen DLLs abhängig wäre. Dies ist ein ernstes Problem, wenn Sie sie nicht korrekt bereitstellen können. Wenn Sie einfach über die Verteilungsprobleme von shdocvw und mshtml.dll googeln, werden Sie sehen, wovon ich spreche. Sie müssen eine 8 MB große Microsoft.mshtml.dll bereitstellen, da diese DLL nicht Teil des .NET-Frameworks ist. In diesem Fall müssen wir eine späte Bindungstechnik verwenden. Schreiben Sie unsere eigenen Wrapper für die oben genannten DLLs. Und natürlich tun wir dies, da dies nützlicher ist als die Verwendung dieser DLLs. Zum Beispiel müssen wir nicht überprüfen, ob der Dokument-Download-Vorgang abgeschlossen ist, da IEHelper dies für uns erledigt.

csexpert
quelle