web-dev-qa-db-ja.com

アーリーバインディングとレイトバインディング

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

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

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

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

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

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

77
Josh

Reflectionインターフェイスを使用しない限り、すべてがC#の初期段階にあります。

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

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

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

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

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


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

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

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

初期バインド

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

遅延バインディング

  • ルックアップは単純なオフセット計算ではなく、通常テキスト比較が行われるため、検索に時間がかかります。
  • ターゲット関数が存在しない可能性があります。
  • ターゲット関数は、渡された引数を受け入れず、誤った型の戻り値を持つ場合があります。
  • 一部の実装では、ターゲットメソッドは実行時に実際に変更できます。そのため、ルックアップは異なる機能を実行する場合があります。これはRuby言語で起こると思います。プログラムの実行中にオブジェクトに新しいメソッドを定義できます。後期バインディングにより、関数呼び出しはメソッドの代わりに既存の基本メソッドを呼び出します。
97
Scott Langham

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

C#4は、dynamicキーワードを使用した遅延バインディングを追加します。詳細については、件名の Chris Burrowのブログエントリ を参照してください。

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

17
Joe Erickson

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

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

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

5
Prasad

早期バインディング

名前自体は、コンパイラがそれがどんな種類のオブジェクトであるか、それが含むすべてのメソッドとプロパティが何であるかをコンパイラが知っていることを説明しています。オブジェクトを宣言するとすぐに、ドットボタンをクリックすると、.NET Intellisenseがそのメソッドとプロパティを設定します。

一般的な例:

ComboBox cboItems;

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

遅延バインディング

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

一般的な例:

オブジェクトobjItems;

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

アーリーバインディングとレイトバインディング

今、写真に登場しています…

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

インテリセンスが自動的に入力されるため、早期バインディングでコードを書くのが簡単です

コンパイルはコンパイル時にチェックされるため、早期バインディングの最小エラー。

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

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

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

3
RajGanesh

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

3
Kumar Nitesh

非常に簡単に言えば、早期バインディングはコンパイル時に行われ、コンパイラーは型とそのすべてのメンバーに関する知識を持ち、遅延バインディングは実行時に行われ、コンパイラーは型とそのメンバーについて何も知りません。これらの概念を説明するYouTubeで素晴らしいビデオを見つけました。

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

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

2
Suresh

この記事は、.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 Browserコントロール)とMshtml.dll(HTML解析およびレンダリングコンポーネント)、または実際にはMshtml.dllの.NETラッパーであるMicrosoft.Mshtml.dllを使用することです。 Internet Explorer-ブラウザについての詳細はこちらから入手できます。

上記の方法とDLLを選択した場合、対処しなければならない問題のいくつかを見てみましょう。

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

1
csexpert