遅延バインディング
バインディング(型を結びつけること)には事前バインディングと遅延バインディングの2種類あります。これもC#とVB.NETで微妙に動作(というかお作法)が違います。
はじめに事前バインディングと遅延バインディングの違いを簡単に説明します。読んで字のごとくなのですが、事前バインディングは宣言時に型を指定して使用する方法、遅延バインディングは実行時に初めてObject型変数に対して代入される型が決定する方法です。
'事前バインディング Dim obj As DateTime '←ここで型が決定 obj = DateTime.Today Console.WriteLine(obj.Month)
'遅延バインディング Dim obj As Object obj = DateTime.Today '←ここで型が決定 Console.WriteLine(obj.Month)
C#ではそもそもこのような書き方ができません。
遅延バインディングはかつてVB6、VBAなどで当たり前のように使われてきました。遅延バインディングはある意味負の遺産と言ってもよいでしょう。また、レガシー機能というだけでなく、実際速度の低下やバグの温床(ランタイムエラー)などになりやすいので、VB.NET環境下においては推奨された手法ではありません。しかし、VB.NETには「Option Strict Off」という機能があります。この場合はほぼVB6スタイルでコードを書くことができますので、遅延バインディングで書いてもエラーは起きません。
sasaki816.hatenablog.com
しかし、「Option Strict On」の状態だと、暗黙の型変換は使用出来なくなる為、当然遅延バインディングも使用出来なくなります。
そもそも論として、遅延バインディングはよほどの事(アンマネージリソースの呼び出しとか)が無い限り使用すべきではないのですが、状況によっては使わざるを得ない場合もあるのです。
例えばVB6のレガシーコードスタイルが強いVB.NETのコードを引き継いで使用したりする場合です。こういった場合、一部を除外しようとすると余りにも影響が大きい事があります。まぁ「影響が大きい=面倒」ということから遅延バインディングで書いているんでしょうけど。
以下は遅延バインディングを使用した場合の回避方法です。手法はたくさんありますが、代表的なものを3つ(+1つおまけ)だけ紹介します。
キャストする
通常は匿名メソッド、ラムダ式を利用した場合によく使う手法ですが、遅延バインディングの回避としても有用です。但し例外が起こりやすいので、忘れずに例外処理を入れましょう。また、キャストする前に型が正しいかどうかの確認を入れるとよいです。
object obj; obj = DateTime.Today; if (obj is DateTime) { Console.WriteLine(((DateTime)obj).Month); }
Dim obj As Object obj = DateTime.Today If TypeOf obj Is System.DateTime Then Console.WriteLine(CType(obj, DateTime).Month) End If
リフレクションを使う
リフレクションを使ってプロパティを取得、実行します。回避方法としてはこの方法が一番安全です。
object obj; obj = DateTime.Today; System.Reflection.PropertyInfo pro = obj.GetType().GetProperty("Month"); if (obj != null) { Console.WriteLine(pro.GetValue(obj).ToString()); }
Dim obj As Object obj = DateTime.Today Dim pro As System.Reflection.PropertyInfo = obj.GetType().GetProperty("Month") If Not pro Is Nothing Then Console.WriteLine(pro.GetValue(obj).ToString()) End If