型名の区別(2)

Variantを使うなと言う説明の中で次のようなプログラムをみかけました。
Dim x,y
x = TextBox1
y = TextBox2
MsgBox x + y
TextBoxというのはVBで使えるGUIのパーツの一つで、文字を入力できる箱のことです。
ふたつの箱に数値を入れるとその合計を表示するという設定のようです。
このプログラムの問題は、例えば3と4を入れると34と表示されてしまうことのようです。
なぜならTextBox1は文字列を返すからであり、xは文字列変数となり、x,yともに文字列だから文字列の結合となってしまうことです。
これを持ってVariantを使うのは危険だとされています。

しかしこのプログラム自体(VBAの仕様含め)がVariant以前に穴が多すぎるのが問題であると考えるべきでしょう。
確かに変数宣言を数値型にすれば数値として計算され期待通りになるのかもしれません。
しかしそれは「たまたま」であり、それで良しとする考えが問題なのです。
少なくともTextBoxが文字列を返すという仕様である(TextBoxが数値であるかをチェックしてから値を返すことはできない)以上は、明示的に数値変換をすべきではないでしょうか。

もっといえば使用者が数値を入れてくれるという前提(期待)をしていることも問題と言えます。
文字をミスタイプで入れてしまうかもしれないのですから。
変数宣言を数値型にしたと仮定しましょう。
Dim x as Long,y as Long
x = TextBox1
y = TextBox2
MsgBox x+y
このプログラムは、数値以外が入力された時点でエラーで停止してしまいます。
いくらVBAで作った“お手軽ソフト”としても、ユーザーの誤操作でプログラムが止まってしまうのはさすがに問題でしょう。

ここでは一度文字列で受け取って、入力された文字列(値)の妥当性をチェックをするべきです。
(わざとエラーにしてON ERROR GOTOを使うというやり方もありますが、あまり推奨されるやり方ではありません)

妥当性チェックと共に文字列を明示的に数値に変換すべきなのです。
例えばIsNumericという「数値ならTrue」を返す組み込み関数を使います。
このチェックでFalseなら「数字以外は入れるな」とユーザーに知らせます。
明示的数値変換はVal関数を使います。
単純に数字かのチェックだけやるとしたら次のようになるでしょう。(実際には数値の範囲のチェックであるとか色々やるべきことはあります。)
Dim x,y
x = TextBox1
y = TextBox2
If IsNumeric(x) Then
x = Val(x)
Else
MsgBox "BOX1に数値が入力されていません"
x = "" End If
If IsNumeric(y) Then
y = Val(y)
Else
MsgBox "BOX2に数値が入力されていません"
y = "" End If
if x <> "" AND y <> "" THEN MsgBox Val(x)+Val(y)
手抜きサンプルを例示して「Variantを使っては駄目」という論理はおかしいとしか思えません。

重要なのはなにかユーザーから値を受け取ったらそれが何であるかをきちんとプログラムで認識して処理をすることではないでしょうか。
よくわからないものをVariantに突っ込むという事自体が問題なのです。

明示的に数値かをチェックするならIsNumeric関数があります。
明示的に数値にするのならVal関数があります。
そういった当り前のことをやらずにVariant悪玉論にすり替えることには疑問に感じます。

別の観点ではこういうチェックをサボるから「セキュリティホール」などのプログラムの脆弱性要因となってしまうのです。
典型的な「オーバーフロー」脆弱性をつくウィルスは過剰なサイズの文字列を突っ込むことで侵入を試みます。
不審者からかもしれないのに「受け取ったもの」をろくにチェックせずに「内部に入れる」から問題となるのです。
comments (0)

コメント

Comment Form