連載

プロフェッショナルVB.NETプログラミング

第26回 言語の動作を選択するオプション(前編)

(株)ピーデー
川俣 晶
2002/11/23

Page1 Page2 Page3

Option Strict

 Option Strict(strictは「厳密な」の意)は、VB.NETで新しく導入されたオプションである。Option Explicitと同様にプロジェクトのプロパティとコード中でOnとOffを指定できる。プロジェクト作成時のデフォルトはOffである。この連載のこれまでのサンプル・プログラムはすべてOption StrictがOffであることを前提としたものであった。では、これをOnにするとどうなるのだろうか? 以下の項目が禁止され、ビルド時にエラーになる。

  • 明示的なキャスト演算子を使用しない縮小変換
  • 遅延バインディング
  • Object 型での=、<>、TypeOf〜Is〜、およびIs以外の演算
  • 宣言でのAs句の省略

 それぞれ、ピンと来ない読者も多いと思うので、実例を示しながら違いを見ていこう。

■明示的なキャスト演算子を使用しない縮小変換

 例えば、以下のようなソース・コードは、プロジェクト作成直後の設定のまま、普通に記述して実行することができる。問題は特に起こらない。

  1: Public Class Form1
  2:   Inherits System.Windows.Forms.Form
  3:
  4: …Windows フォーム デザイナで生成されたコード…
  5:
  6:   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  7:     Dim a As Long
  8:     Dim b As Integer
  9:     a = 123
 10:     b = a
 11:     Trace.WriteLine(b)
 12:   End Sub
 13: End Class
Long型とInteger型の2つの変数を使用したサンプル・プログラム4

 このソース・コードの先頭に次の1行を書き込んで、機能をオンにしてみるとどうなるだろうか。

Option Strict On

 すると、ビルド時に以下のようなエラーが発生する。

 1: Q:\aWrite\@it\vbn\022\smpl\Sample004n2\Form1.vb(51) : error BC30512: Option Strict On で 'Long' から 'Integer' への暗黙的な変換はできません。
サンプル・プログラム4の先頭にOption Strict Onを書き込んだ場合に発生するビルド・エラー

 このようなエラーが発生するのは、Long型の値をInteger型に代入しようとしているからである。Long型の方がInteger型よりも表現できる値の範囲が広いので、このような変数の代入は、もしかしたらオーバー・フローエラーを発生させる可能性を持っている。代入される数値がInteger型で表現可能だと判断し、安全だと分かってこのような代入を意図的に書く場合もあるが、そうでない場合もある。例えば、変数を宣言するときに、間違えてLongのつもりでIntegerと書いてしまうこともある。そのような場合、ビルド時にエラーになれば、容易に書き間違いに気付くことができる。Option Strict Onとは後者のメリットを重視したモードである。

 では、安全だと分かっているときに、どのように記述すれば、ビルド・エラーが発生しないようにできるのだろうか? キャストというものを行うことで、これは回避できる。以下にキャスト機能を付加してビルド可能にしたソース・コードを示す。

  1: Option Strict On
  2:
  3: Public Class Form1
  4:   Inherits System.Windows.Forms.Form
  5:
  6: …Windows フォーム デザイナで生成されたコード…
  7:
  8:   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  9:     Dim a As Long
 10:     Dim b As Integer
 11:     a = 123
 12:     b = CInt(a)
 13:     Trace.WriteLine(b)
 14:   End Sub
 15: End Class
サンプル・プログラム4を、キャストを使用してOption Strict Onでもビルド可能にしたサンプル・プログラム5

 このソース・コードの12行目のCInt関数を見ていただきたい。CIntはVB 6にも存在していたものだが、VB.NETでは特にキャストという役割を与えられている。CIntは引数の値を明示的にInteger型に変換する役割を持つ。これを記述することで、プログラマーは間違いなく、Long型をInteger型に変換するために、この式を書いたことが明示される。

 VB 6プログラマーならご存じのとおり、Integer型に変換するCIntのほかに、ほかの型に明示的に変換するCBool、CByte、CChar、CDate、CDec、CDbl、CLng、CObj、CShort、CSng、CStrといった関数が存在している。

 クラス・ライブラリのクラスや、自作クラスのデータ型を変換する場合はどうだろうか。例えば、以下のようなソース・コードがあったとする。

  1: Public Class A
  2: End Class
  3:
  4: Public Class B
  5:   Inherits A
  6: End Class
  7:
  8: Public Class Form1
  9:   Inherits System.Windows.Forms.Form
 10:
 11: …Windows フォーム デザイナで生成されたコード…
 12:
 13:   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
 14:     Dim objA As A
 15:     Dim objB As B
 16:     objA = New B()
 17:     objB = objA
 18:   End Sub
 19: End Class
2つの自作クラスの間でデータ型の変換を行っているサンプル・プログラム6

 これは問題なくビルドできるが、先頭行にOption Strict Onを書き込むと以下のようなエラーが発生するようになる。

 1: Q:\aWrite\@it\vbn\022\smpl\Sample005n2\Form1.vb(58) : error BC30512: Option Strict On で 'Sample005n2.A' から 'Sample005n2.B' への暗黙的な変換はできません。
サンプル・プログラム6の先頭にOption Strict Onを書き込んだ場合に発生するビルド・エラー(エラーとなっている58行目は、上記のサンプル・プログラム6では17行目)

 スーパークラスからサブクラスへの変換はエラーとして扱われたことが分かるだろう。しかし、サブクラスからスーパークラスへの変換はエラーになっていない(16行目)。この場合、何の情報の欠落もなく変換できるので、エラーになっていない。しかし、あるクラスを継承したクラスは複数存在する可能性があるので、逆の代入はデータ型が整合するという保証はない。そのため、17行目はOption Strict Onではエラー扱いになっている。プログラマーが自分で確認して問題ないと分かっている場合は、CTypeまたはDirectCast関数を用いて、変換させたいという意図を明示的にソース・コードに書き込む。

  1: Option Strict On
  2:
  3: Public Class A
  4: End Class
  5:
  6: Public Class B
  7:   Inherits A
  8: End Class
  9:
 10: Public Class Form1
 11:   Inherits System.Windows.Forms.Form
 12:
 13: …Windows フォーム デザイナで生成されたコード…
 14:
 15:   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
 16:     Dim objA As A
 17:     Dim objB As B
 18:     objA = New B()
 19:     objB = CType(objA, B)
 20:   End Sub
 21: End Class
サンプル・プログラム6を、CType関数により明示的に型変換するように書き換えたサンプル・プログラム7

 このソース・コードの19行目に書き込まれたCTypeが明示的に変換を行う意図を示したものである。CTypeの第1引数が変換したい値である。第2引数は、変換結果となるべきデータ型である。こう記述すればビルド・エラーにならない。

 DirectCast関数を用いる場合は、CTypeの代わりにDirectCastと書き込む。CTypeとDirectCastの違いは、変換することができる対象範囲の違いである。CTypeは変換できるものなら何でも変換してくれる。しかし、DirectCastはクラス階層の下位方向への変換しか行わず、また値型も扱えないので、Long型からInteger型への変換などには使用できない。機能が少ない分だけ、DirectCastの方が高速に実行される。

次回予告

 今回はOption Strict Onでビルド・エラーとなる4つの項目のうち、キャストを使用しない縮小変換までを解説した。次回は引き続き、残る3つの項目と、Option Compare、整数のオーバーフロー・チェックのオプションについて解説する予定だ。End of Article


 INDEX
  連載 プロフェッショナルVB.NETプログラミング
  第26回 言語の動作を選択するオプション(前編)
    1.オプション機能
    2.オプション指定の適用範囲
  3.Option Strict
 
「プロフェッショナルVB.NETプログラミング」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間