早期および遅延バインディング


83

C#でアーリー/レイトバインディングが発生したときに頭を悩ませようとしています。

非仮想メソッドは常に早期にバインドされます。仮想メソッドは常にレイトバウンドです。コンパイラーは、実行時にバインドする実際のメソッドを解決するために追加のコードを挿入し、型の安全性をチェックします。したがって、サブタイプのポリモーフィズムは遅延バインディングを使用します。

リフレクションを使用してメソッドを呼び出すことは、遅延バインディングの例です。コンパイラではなく、これを実現するコードを記述します。(たとえば、COMコンポーネントの呼び出し。)

VB.NETは、Option Strictがオフの場合、暗黙的な遅延バインディングをサポートします。オブジェクトは、Object型であると宣言された変数に割り当てられると、レイトバウンドされます。VBコンパイラは、実行時に適切なメソッドにバインドし、無効な呼び出しをキャッチするコードを挿入します。C#はこの機能をサポートしていません。

私は正しい方向に向かっていますか?

デリゲートを呼び出し、インターフェイス参照を介してメソッドを呼び出すのはどうですか?それは初期バインディングですか、それとも遅延バインディングですか?

回答:


102

Reflectionインターフェイスを経由しない限り、すべてがC#で早期にバインドされます。

アーリーバウンドとは、コンパイル時にターゲットメソッドが検出され、これを呼び出すコードが作成されることを意味します。仮想かどうか(呼び出し時にそれを見つけるための追加の手順があることを意味します)。メソッドが存在しない場合、コンパイラはコードのコンパイルに失敗します。

レイトバウンドとは、ターゲットメソッドが実行時にルックアップされることを意味します。多くの場合、メソッドのテキスト名が検索に使用されます。メソッドがない場合は、強打します。プログラムはクラッシュするか、実行時に何らかの例外処理スキームに入ります。

ほとんどのスクリプト言語は遅延バインディングを使用し、コンパイル言語は早期バインディングを使用します。

C#(バージョン4より前)は遅延バインディングを行いません。ただし、リフレクションAPIを使用してそれを行うことができます。そのAPIは、実行時にアセンブリを掘り下げて関数名を検索するコードにコンパイルされます。Option Strictがオフになっている場合、VBは遅延バインディングを実行できます。

通常、バインドはパフォーマンスに影響を与えます。遅延バインディングは実行時にルックアップを必要とするため、通常、メソッド呼び出しは早期バインドされたメソッド呼び出しよりも遅いことを意味します。


通常の関数の場合、コンパイラーはメモリー内のその数値位置を計算できます。次に、関数が呼び出されると、このアドレスで関数を呼び出すための命令を生成できます。

仮想メソッドを持つオブジェクトの場合、コンパイラはvテーブルを生成します。これは基本的に、仮想メソッドのアドレスを含む配列です。仮想メソッドを持つすべてのオブジェクトには、vテーブルのアドレスであるコンパイラによって生成された非表示のメンバーが含まれます。仮想関数が呼び出されると、コンパイラはvテーブル内の適切なメソッドの位置を計算します。次に、オブジェクトのvテーブルを調べ、この位置で仮想メソッドを呼び出すコードを生成します。

そのため、仮想関数に対して発生するルックアップがあります。これは大幅に最適化されているため、実行時に非常に迅速に実行されます。

アーリーバウンド

  • コンパイラーは、呼び出された関数がコンパイル時にどこにあるかを計算できます。
  • コンパイラーは、関数が存在し、実行時に呼び出すことができることを早期に(プログラム・コードが実行される前に)保証できます。
  • コンパイラーは、関数が正しい数の引数を取り、それらが正しい型であることを保証します。また、戻り値が正しいタイプであることも確認します。

遅延バインディング

  • 単純なオフセット計算ではないため、ルックアップには時間がかかります。通常、テキスト比較が行われます。
  • 対象の機能が存在しない可能性があります。
  • ターゲット関数は、渡された引数を受け入れない可能性があり、間違ったタイプの戻り値を持っている可能性があります。
  • 一部の実装では、ターゲットメソッドは実行時に実際に変更される可能性があります。したがって、ルックアップは別の機能を実行する可能性があります。これはRuby言語で発生すると思います。プログラムの実行中に、オブジェクトに新しいメソッドを定義できます。遅延バインディングを使用すると、関数呼び出しで、既存の基本メソッドを呼び出す代わりに、メソッドの新しいオーバーライドの呼び出しを開始できます。

「VB言語自体は遅延バインディングではありません...」と言うつもりだったと思います
Michael Meadows

実は私はVBを使っていないので…よくわかりません。私はC#を意味しましたが、私は自分自身を繰り返していたようです。あなたが正しいと思いますが、修正します!
スコットランガム

21
動的型付けは遅延バインディングと同じではありません。違いは微妙ですが、それは重要です。遅延バインディングは引き続き型にバインドし、実行時に実行するだけです。動的型付けはバインドされません。代わりに、タイプに関係なく、実行時にメンバー情報を解決します。
マイケルメドウズ

1
仮想メソッドを持つオブジェクトの場合、コンパイラはvテーブルを生成します。」これは少し間違っています-「オブジェクト」ではなく「クラス」。
turdus-merula 2014

1
@IvanRuskiそうは思いません。コンパイル時には、デリゲートが受け入れるすべての引数タイプがわかっています。したがって、実行時(「遅い」)ではなくコンパイル時(「早い」)に、コンパイラーは呼び出しが機能することを保証できます。
スコットランガム

18

C#3は早期バインディングを使用します。

C#4は、dynamicキーワードで遅延バインディングを追加します。詳細については、この件に関するChrisBurrowのブログエントリを参照してください。

仮想メソッドと非仮想メソッドに関しては、これは別の問題です。を呼び出すstring.ToString()と、C#コードは仮想object.ToString()メソッドにバインドされます。呼び出し元のコードは、オブジェクトのタイプに基づいて変更されません。むしろ、仮想メソッドは関数ポインタのテーブルを介して呼び出されます。オブジェクトのインスタンスは、そのToString()メソッドを指すオブジェクトのテーブルを参照します。文字列のインスタンスには、そのメソッドを指す仮想メソッドテーブルがありますToString()。はい、これはポリモーフィズムです。ただし、遅延バインディングではありません。


1
私はこの説明に完全には同意しません。C#では、インスタンスメソッドまたはフィールドを仮想手段としてマークすると、派生型は継承チェーンの基本型の実装をオーバーライドできます。仮想メソッドを使用すると、CLRは、実行時オブジェクトインスタンスに基づいて、実行時に呼び出すメソッドを認識します。おそらく、私があなたに同意する唯一の部分は、それがポリモーフィズムの実装であるということです。次に、遅延バインディングではないと言って混乱を引き起こします。CLRは、オブジェクトインスタンスの実行時型を認識している場合にのみ、正しい実行時型実装を呼び出すことができるため、遅延バインディングです。
Julius Depulla 2016年

6

ほとんどの場合、早期バインディングは私たちが日常的に行うことです。たとえばEmployee、コンパイル時に使用可能なクラスがある場合、そのクラスのインスタンスを作成し、インスタンスメンバーを呼び出すだけです。これは初期のバインディングです。

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

一方、コンパイル時にクラスの知識がない場合、唯一の方法はリフレクションを使用して遅延バインディングを使用することです。私はこれらの概念を説明する素晴らしいビデオに出くわしました-ここにリンクがあります。


3

非常に古い投稿ですが、さらに情報を追加したいと考えていました。遅延バインディングは、コンパイル時にオブジェクトをインスタンス化したくない場合に使用されます。でC#ご使用Activator実行時にバインドオブジェクトを呼び出すこと。


3

早期バインディング

名前自体は、コンパイラがオブジェクトの種類、含まれているすべてのメソッドとプロパティを認識していることを示しています。オブジェクトを宣言するとすぐに、.NETIntellisenseはドットボタンをクリックするとメソッドとプロパティを設定します。

一般的な例:

ComboBox cboItems;

ListBox lstItems; 上記の例では、cboItemを入力し、ドットの後にドットを配置すると、コンパイラーはコンボボックスであることを既に認識しているため、コンボボックスのすべてのメソッド、イベント、およびプロパティに自動的にデータが入力されます。

遅延バインディング

名前自体は、コンパイラがオブジェクトの種類、含まれているすべてのメソッドとプロパティを認識していないことを示しています。オブジェクトとして宣言する必要があります。後で、オブジェクトのタイプ、オブジェクトに格納されているメソッドを取得する必要があります。すべては実行時に認識されます。

一般的な例:

オブジェクトobjItems;

objItems = CreateObject( "DLLまたはアセンブリ名"); ここでは、コンパイル時にobjItemsのタイプは決定されません。dllのオブジェクトを作成し、それをobjItemsに割り当てるため、すべてが実行時に決定されます。

早期バインディングと遅延バインディング

今、絵に来ています…

ここではボックス化またはボックス化解除が行われないため、アプリケーションは早期バインディングでより高速に実行されます。

インテリセンスが自動的に入力されるため、アーリーバインディングでコードを記述しやすくなります

構文はコンパイル時にチェックされるため、アーリーバインディングのエラーは最小限に抑えられます。

すべてが実行時に決定されるため、遅延バインディングはすべての種類のバージョンでサポートされます。

遅延バインディングが使用されている場合、将来の機能拡張におけるコードの影響は最小限に抑えられます。

パフォーマンスは初期バインディングのコードになります。どちらにも長所と短所があり、シナリオに基づいて適切なバインディングを選択するのは開発者の決定です。


2

非常に簡単に言えば、アーリーバインディングはコンパイル時に発生し、コンパイラーは型とそのすべてのメンバーについての知識を持ち、レイトバインディングは実行時に発生します。コンパイラーは型とそのメンバーについて何も知りません。私はこれらの概念を説明するYouTubeで素晴らしいビデオに出くわしました。

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

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


1

この記事は、.netコンポーネントを構築し、実行時に実行時バインディングを使用してVb6プロジェクトで使用し、そのイベントを添付してコールバックを取得するためのガイドです。

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

この記事は、.NETコンポーネントを構築し、それをVB6プロジェクトで使用するためのガイドです。この問題に関するサンプルはたくさんありますが、なぜ新しいサンプルを作成したのですか?私の謙虚な意見では、他の記事では、欠落している部分は実行時にそのイベントを添付することです。したがって、この記事では、.NETコンポーネントを作成し、COM表示コンポーネントとしてマークし、実行時にVB6で使用して、そのイベントにアタッチします。

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

ほとんどの開発者は、Internet Explorerの自動化を必要とすることがよくあります。これは、基本的に、ブラウザーを開き、いくつかのフォームに入力し、プログラムでデータを投稿することを意味します。

最も一般的なアプローチは、shdocvw.dll(Microsoft Webブラウザーコントロール)とMshtml.dll(HTML解析およびレンダリングコンポーネント)、または実際にはMshtml.dllの.NETラッパーであるMicrosoft.Mshtml.dllを使用することです。Internet Explorerの詳細については、こちらのブラウザについてをご覧ください。

上記のメソッドとDLLを選択した場合は、対処しなければならない可能性のある問題のいくつかを見てみましょう。

プロジェクトはこれらのDLLに依存するため、これらのDLLを配布する必要があります。これは、正しく展開できない場合に深刻な問題になります。shdocvwとmshtml.dllの配布の問題についてグーグルを実行するだけで、私が話していることがわかります。このDLLは.NETFrameworkの一部ではないため、8MBのMicrosoft.mshtml.dllを展開する必要があります。この場合、実行する必要があるのは、遅延バインディング手法を使用することです。上記のDLL用に独自のラッパーを作成します。そしてもちろん、これらのDLLを使用するよりも便利なので、これを行います。たとえば、IEHelperがこれを行うため、ドキュメントのダウンロード操作が完了したかどうかを確認する必要はありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.