88

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

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

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

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

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

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

4

7 に答える 7

106

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

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

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

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

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

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


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

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

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

アーリーバウンド

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

遅延バインディング

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

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

dynamicC# 4 では、キーワードによる遅延バインディングが追加されています。詳細については、このテーマに関するChris Burrow のブログ エントリを参照してください。

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

于 2009-01-27T17:53:04.277 に答える
6

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

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

一方、コンパイル時にクラスの知識がない場合、唯一の方法はリフレクションを使用してレイト バインドすることです。これらの概念を説明する優れたビデオを見つけました。ここにリンクがあります。

于 2012-07-09T14:57:44.610 に答える
3

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

于 2012-09-27T18:45:11.963 に答える
2

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

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

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

于 2012-09-04T12:14:42.553 に答える
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 を配布する必要があります。これらの DLL を正しく展開できないと、深刻な問題になります。shdocvw と mshtml.dll の配布の問題についてグーグル検索を行うだけで、私が話していることがわかります。この DLL は .NET フレームワークの一部ではないため、8 MB の Microsoft.mshtml.dll を展開する必要があります。この場合、実行する必要があるのは、遅延バインディング手法を使用することです。上記の DLL 用の独自のラッパーを作成します。もちろん、これらの DLL を使用するよりも便利なので、これを行います。たとえば、ドキュメントのダウンロード操作が完了したかどうかを確認する必要はありません。これは IEHelper が行うためです。

于 2010-04-26T08:48:26.410 に答える