ちょっと聞きなれない言葉ですが、プログラミングのメカニズムとして
遅延バインディング(late binding, dynamic binding)と
事前バインディング(early binding)
という二つのバインディング方法があります。
少し似た概念としてダイナミックリンク、スタティックリンクという概念がありますが、これとは異なる概念です。
目次
遅延バインディングと事前バインディングの違い
遅延バインディングとは、実行時にバインディングが行われることを言います。
プログラムの実行時、オブジェクトが名前で参照されるタイミングで、メソッドが呼び出されます。
事前バインディングとは、コンパイル時にバインディングが行われることを言います。
コンパイル時にすべての変数やメソッドが確定され、実行時に呼び出されます。
ちょっとわかりにくいので概念図を書いてみます。
クラスT2014にAAA()、BBB()というメソッドが元々あったとします。
ある時、ライブラリのバージョンアップが行われメソッドAAA()が削除され、メソッドCCC()が追加されたとします。
この後、元のコードがどのような振る舞いをするかをまとめたのが上の図です。
事前バインディングではコンパイル時にエラーが発生しますが、遅延バインディングではコンパイル時にエラーが発生しません。
ただ、遅延バインディングでも存在しないメソッドAAA()を呼び出すと実行時エラーとなります。
つまり、遅延バインディングは外部ライブラリがバージョンアップしてもコンパイルエラーを防ぐ効果があります。
遅延バインディングのエラーは次の通りです。
実行時エラー ‘438’
オブジェクトは、このプロパティまたはメソッドをサポートしていません。
事前バインディングのエラーは次の通りです。
コンパイルエラー:
メソッドまたはデータ メンバーが見つかりません。
遅延バインディングと事前バインディングの比較
遅延バインディングと事前バインディングの違いを比較してみました。
種類 | 遅延バインディング | 事前バインディング |
バインディングのタイミング | 実行時 | コンパイル時 |
速度 | 遅い | 速い |
宣言方法 | Object型で宣言する | オブジェクトのタイプで宣言する |
プログラムの可読性 | コードの中で実際に使われるオブジェクトが分かりくい | コードの中でオブジェクトが分かるために可読性高いIDEの中で使われるメソッドが明確になる |
遅延バインディングは、C++、.NET(VBやC#)、Javaで実装されています。
通常は事前バインディングが勧められます。
それでも、遅延バインディングが勧められるケースがあります。
以下はその説明です。
遅延バインディングが勧められるケース
いろいろと調べてみると、遅延バインディングが最も勧められるとして、Excelのバージョン違いを吸収するプログラムを書くときがあるようです。
遅延バインディングを用いることにより、いろいろな記事でExcelのバージョンの違いを吸収できるコードが書けるとの説明が載っています。
ただ、これは厳密には正しくないと思います(おそらく)。
一番上の概念図の通り、遅延バインディングを使って、存在しないメソッドを使ってしまうと、実行時エラーになってしまうからです。
とは言え、ある程度の大雑把なメソッドはどのExcelのバージョンでも共通で、Excel 2000、2003、2007とバージョンが上がるにしたがって、中身だけが新しくなっていると考えれば、遅延バインディングを用いればほとんどのケースではバージョンに依存しないコードが書けるようです。
というわけで、ExcelやWordを扱うプログラムを書く際は遅延バインディングを用いましょう。
遅延バインディングと事前バインディングのコードサンプル(C#)
遅延バインディングについて、VBによるサンプルはよく見かけるのですが、C#によるサンプルはほとんど見かけません。
C#で遅延バインディングを使うには、Activator.CreateInstance を使います。
以下にとても分かりやすいサンプルが載っていました。
上記のソースから引用します。
遅延バインディングのサンプル
フォームを作成し、ボタンを貼り付けます。ボタンクリックのイベントを変更します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
private void button1_Click(object sender, System.EventArgs e) { object objApp_Late; object objBook_Late; object objBooks_Late; object objSheets_Late; object objSheet_Late; object objRange_Late; object[] Parameters; try { // Get the class type and instantiate Excel. Type objClassType; objClassType = Type.GetTypeFromProgID("Excel.Application"); objApp_Late = Activator.CreateInstance(objClassType); //Get the workbooks collection. objBooks_Late = objApp_Late.GetType().InvokeMember( "Workbooks", BindingFlags.GetProperty, null, objApp_Late, null ); //Add a new workbook. objBook_Late = objBooks_Late.GetType().InvokeMember( "Add", BindingFlags.InvokeMethod, null, objBooks_Late, null ); //Get the worksheets collection. objSheets_Late = objBook_Late.GetType().InvokeMember( "Worksheets", BindingFlags.GetProperty, null, objBook_Late, null ); //Get the first worksheet. Parameters = new Object[1]; Parameters[0] = 1; objSheet_Late = objSheets_Late.GetType().InvokeMember( "Item", BindingFlags.GetProperty, null, objSheets_Late, Parameters ); //Get a range object that contains cell A1. Parameters = new Object[2]; Parameters[0] = "A1"; Parameters[1] = Missing.Value; objRange_Late = objSheet_Late.GetType().InvokeMember( "Range", BindingFlags.GetProperty, null, objSheet_Late, Parameters ); //Write "Hello, World!" in cell A1. Parameters = new Object[1]; Parameters[0] = "Hello, World!"; objRange_Late.GetType().InvokeMember( "Value", BindingFlags.SetProperty, null, objRange_Late, Parameters ); //Return control of Excel to the user. Parameters = new Object[1]; Parameters[0] = true; objApp_Late.GetType().InvokeMember( "Visible", BindingFlags.SetProperty, null, objApp_Late, Parameters ); objApp_Late.GetType().InvokeMember( "UserControl", BindingFlags.SetProperty, null, objApp_Late, Parameters ); } catch( Exception theException ) { String errorMessage; errorMessage = "Error: "; errorMessage = String.Concat( errorMessage, theException.Message ); errorMessage = String.Concat( errorMessage, " Line: " ); errorMessage = String.Concat( errorMessage, theException.Source ); MessageBox.Show( errorMessage, "Error" ); } } |
事前バインディングのサンプル
フォームを作成し、ボタンを貼り付けます。ボタンクリックのイベントを変更します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
private void button1_Click(object sender, System.EventArgs e) { Excel.Application objApp; Excel._Workbook objBook; Excel.Workbooks objBooks; Excel.Sheets objSheets; Excel._Worksheet objSheet; Excel.Range range; try { // Instantiate Excel and start a new workbook. objApp = new Excel.Application(); objBooks = objApp.Workbooks; objBook = objBooks.Add( Missing.Value ); objSheets = objBook.Worksheets; objSheet = (Excel._Worksheet)objSheets.get_Item(1); range = objSheet.get_Range("A1", Missing.Value); range.set_Value(Missing.Value, "Hello, World!" ); //Return control of Excel to the user. objApp.Visible = true; objApp.UserControl = true; } catch( Exception theException ) { String errorMessage; errorMessage = "Error: "; errorMessage = String.Concat( errorMessage, theException.Message ); errorMessage = String.Concat( errorMessage, " Line: " ); errorMessage = String.Concat( errorMessage, theException.Source ); MessageBox.Show( errorMessage, "Error" ); } } |
プログラミングの無料レッスン体験
約8,000名の受講生と80社以上の導入実績のあるプログラミングやWebデザインのオンラインマンツーマンレッスンCodecamp
<Codecampの特徴>
1 現役エンジニアによる指導
2オンラインでのマンツーマン形式の講義
3大手企業にも導入されている実践的なカリキュラム
↓無料体験レッスン実施中です。
コメント
この記事を参考に遅延バインディングでExcelの出力を実装することができました。
とても助かりました。
あともう一つ、値を書き込んだ後、列幅の自動調整(Autofit)を行いたいのですが、
どのように設定したら良いかご教示いただけませんでしょうか?
[…] 遅延バインディング(late binding, dynamic binding)と事前バインディング(early bindi… […]