型名の区別

そもそもなぜ変数の型宣言が必要なのでしょうか。
一つは変数への監視を強めて想定外の数値などが混入したりを防ぐという理由があります。
しかしVBAではそれができていないのです。
余りに無節操に、暗黙のうちにキャスト(型変換)が行われてしまい、制御されていないということなのです。

プログラムを実際に作って。どのような動作をするのか確認していきます。
Dim a_var As Variant, a_int As Integer, a_str As String
a_str = 123
a_var = a_str
a_int = a_str
Debug.Print a_str
Debug.Print a_var
Debug.Print a_int
このプログラムは全く問題なく動きます。
Debug.Printというのはデバッグコンソールに表示するものであり、動作確認をする時に多用するデバッグ手段の一つです。

ここで表示された結果をよく見るとa_str,a_varとa_intの値の表示が微妙に違うことが分かります。
a_intは頭に空白文字が1つはいり、a_varとa_strにはありません。
これはa_intが数値表示なので正負記号が入るところに空白文字が表示されていると考えられます。
つまり数値として扱われていると言うことです。

このことから
a_strには数値から文字列に変換されて代入されている。
a_varは文字列型から代入されれば文字列型として扱う。
a_intは暗黙で文字列型から数値型へ変換されている。
ということが推察されます。
裏側では一生懸命ややこしいことをやっているようなのですが、結果としては歓迎すべき動きとは言えないのが困ったものなのです。
特に一つ目は数値定数を文字列変数に代入しているのですが、エラーでは無く許容されます。普通の言語ではまず許容されないので殆どの人の常識外であり、デバッグでハマる原因になりかねません。

以下のプログラムはどうでしょうか。
Dim a_var As Variant, a_int As Integer, a_str As String
a_int = "123"
a_var = a_int
a_str = a_int
Debug.Print a_str
Debug.Print a_var
Debug.Print a_int
え?と今度はさすがに感じると思うのですが、これも全く問題なく動いてしまうのです。
結果を見ると、今度はa_varとa_intの値の表示の前に空白が入っているのです。
a_intには文字列から数値に変換されて代入されています。
a_varは数値型から代入されたので数値として扱います。
a_strは暗黙で数値型から文字列型へ変換しています。

特に一つ目は文字定数を数値変数に代入しているのですが、これすらもエラーでは無く許容されます。さすがにこれは驚きです。普通の言語ではあり得ないでしょう。

このように変数の方を明示的に型宣言をし、定数も文字か数字か明確に違うものを指定してすら、許容し暗黙的に変換してスルーされてしまうのです。
これでは型宣言した意味がないも同然でしょう。
異なる型同士の不整合チェックを期待するからこそ、型宣言をするという意味があるのですから。

つまり、このような状況であるならばVariant型にして、それをどう扱うかを意識しながら扱った方が良いと考えられます。
特に多少なりともプログラムの経験があるのならなおさら勘違いしてバグを見過ごしやすくなってしまいます。 経験が無い人ならなおさら、こんな状況に慣れるべきでは無いと考えます。

さて、もう少し突っ込んでいきます。
Dim a_var As Variant, a_int As Integer, a_str As String
a_str = "123a"
a_var = a_str
a_int = a_str
Debug.Print a_str
Debug.Print a_var
Debug.Print a_int
今度はさすがに「a_int = a_str」で型変換エラーが出ました。
変換できないのはさすがに看過できないようです。

続いて‘+’演算子の処理を見てみましょう。
Dim a_var As Variant, a_int As Integer, a_str As String
a_int = 123
a_var = a_int
a_str = a_int
Debug.Print a_str + a_str
Debug.Print a_var + a_int
Debug.Print a_var + a_str
Debug.Print a_var + a_var
Debug.Print a_int + a_int
123123
246
246
246
246
Dim a_var As Variant, a_int As Integer, a_str As String
a_str = 123
a_var = a_str
a_int = a_str
Debug.Print a_str + a_str
Debug.Print a_var + a_int
Debug.Print a_var + a_str
Debug.Print a_var + a_var
Debug.Print a_int + a_int
123123
246
123123
123123
246
これらの結果から‘+’演算子の処理は次の法則になるようです。
・数値同士なら算術加算となる。
・要素に文字列型と数値型が混合していると文字列が数値変換されて算術加算となる。
・文字列同士なら文字列として結合される。
という動作になります。
このこともバグを誘引する要因になりかねないので注意が必要でしょう。

次の例題です。
a = "320"
Debug.Print a + "2"
Debug.Print a + 3
b = 320
Debug.Print b + "2"
Debug.Print b + 3
322
323
3202
323
この結果に違和感を感じないでしょうか。
実は変数の型名定義によってはこうなるのです。
Dim a As Long, b As String
うっかりすると、こんな変なことにもなるのです。
VBAでは型名定義というのはブロック変数定義もありませんし、頭の方でまとめてやるのが通例になってしまいます。
結果としてこういうミスをしがちになります。

変数の管理をちゃんとやっていなかったのが問題なのだ、というのも正論かもしれません。
しかしきちんとLongやStringと型名宣言したが故にバグを誘引してしまった、とも言えます。
もしこれが
Dim a As Variant, b As Variant
であったのならば
3202
323
322
323
となり、期待通りの結果ではないでしょうか。
結果オーライという話では無く、型名宣言すると変な動きを誘引してしまう例の一つです。

本来はこうすべきという筋に話を戻しましょう。
ここに出てくるval関数は文字列を明示的に数値に変換する関数です。
Dim a, b, c '←全てVariant
a = "320"
b = "400"
c = a + b
Debug.Print c
c = val(a) + val(b)
Debug.Print c
一つ目のDebug.Printは文字列の連結になるので320400。
二つ目はDebug.Printは変数a,bを数値に変換して数値加算となり720。

先ほどプラス演算子は算術加算と文字列結合の両方の機能をもってしまっている、と解説しました。
これもあまり良いものではないので、せめて文字列結合には"&"を使うとよいでしょう。
Dim a, b, c '←全てVariant
a = "320"
b = "400"
c = a & b
Debug.Print c
c = val(a) + val(b)
Debug.Print c
この演算子は必ず文字列として結合してくれますので
a = 320
b = 400
c = a & b
こんな場合でも変数の値は両方とも文字列変換されて結合され、cは320400となります。

ここで本来はこうあるべきということで、例えば変数に型のない言語としてPerlをあげてみます。
Perlでは変数の名前の前に$をつけるのでそのことは了解して見てください。
$a = "320";
$b = "400";
print $a + $b;
print $a.$b;
“+”は常に数値演算子としての加算を行うので期待道理の結果となります。
“.”は文字列として結合する演算子なので、結果は320400となり、これも期待通りとなります。
こういう形にしさえすれば混乱が少なかったのにと思います。
+演算子の定義については、BASICとしての互換に拘ったのかもしれませんが、結果として混乱を招いてしまっています。
とはいっても取り返しはつかないので、Variant型を使うべし、という作法を薦めるざるを得ないのです。

Variant型は良くない、使うべきではないという論旨の話もよく見かけます。
暗黙の型変換をせずに(もしくはごく限定的として殆どを)エラーとしてくれるのならそれも納得します。 しかし現実はそうではないのです。 VBAはとても“残念な”言語であるという事実は不幸としか言いようがありません。

使用者である我々ができることは、こういう言語仕様だと言うことを認識して注意深く使っていくしかないでしょう。
comments (2)

コメント

http://fantasticbandan76.exteen.com/20150702/contracted-toe-surgery | 2017/07/31 04:10 PM
I visited various web pages but the audio feature for audio
songs current at this web site is actually marvelous.

Comment Form