連載

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

Chapter 04 演算子と関数の変化

株式会社ピーデー 川俣 晶
2004/04/01
Page1 Page2


 本記事は、(株)技術評論社が発行する書籍『VB6プログラマーのための入門 Visual Basic .NET 独習講座』の一部分を許可を得て転載したものです。同書籍に関する詳しい情報については、本記事の最後に掲載しています。
Eqv演算子とImp演算子

 VB 6には、Eqv演算子とImp演算子という演算子があった。これは、はるか遠い祖先のBASICから受け継いだ演算子で歴史は長い。しかし、これらの演算子が有効に活用された事例があるかというと、残念ながら筆者はそのようなものを知らない。ほかの演算子の組み合わせでも容易に実現できるものであり、なくてもあまり問題にならないのではないかと思っていたが、とうとうVB.NETでなくなってしまった。

 リスト4-10は、VB 6でこれらの演算子を使った例である。

 1: Private Sub Form_Load()
 2:   For i = -1 To 0
 3:     For j = -1 To 0
 4:       Debug.Print i; " Eqv "; j; "="; i Eqv j
 5:     Next
 6:   Next
 7:   For i = -1 To 0
 8:     For j = -1 To 0
 9:       Debug.Print i; " Imp "; j; "="; i Imp j
10:     Next
11:   Next
12: End Sub
リスト4-10 Eqv演算子とImp演算子を使用したプログラム

 これを実行すると以下のようになる。

1: -1  Eqv -1 =-1
2: -1  Eqv  0 = 0
3:  0  Eqv -1 = 0
4:  0  Eqv  0 =-1
5: -1  Imp -1 =-1
6: -1  Imp  0 = 0
7:  0  Imp -1 =-1
8:  0  Imp  0 =-1
リスト4-11 リスト4-10の実行結果

 これと同じ結果が得られるようにVB.NETで記述したプログラムが、リスト4-12である。

 1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
 2:   Dim i, j As Integer
 3:   For i = -1 To 0
 4:     For j = -1 To 0
 5:       Trace.WriteLine(i & " Eqv " & j & "=" & Not (i Xor j))
 6:     Next
 7:   Next
 8:   For i = -1 To 0
 9:     For j = -1 To 0
10:       Trace.WriteLine(i & " Imp " & j & "=" & ((Not i) Or j))
11:     Next
12:   Next
13: End Sub
リスト4-12 リスト4-10と同じ結果を得るVB.NETのプログラム

 これを実行すると次のようになる。

1: -1 Eqv -1=-1
2: -1 Eqv 0=0
3: 0 Eqv -1=0
4: 0 Eqv 0=-1
5: -1 Imp -1=-1
6: -1 Imp 0=0
7: 0 Imp -1=-1
8: 0 Imp 0=-1
リスト4-13 リスト4-12の実行結果

 見てのとおり、Not、Xor、Orなどを組み合わせるだけで等価の結果が得られる

 Eqvに関しては、このプログラムのように処理せず、「=」演算子で代用できるケースも多いだろう。Boolean値が同じかどうかを調べるという動作であれば、「=」演算子でも同じことが実現されるからだ。ただし、演算子の優先順位が違うので、演算子を置き換える際は注意が必要である。同じ順番で演算させるために、必要に応じて括弧などを補おう。

AndAlso演算子とOrElse演算子

 VB.NETには、効率よくAndやOrを含む条件判断を行うAndAlso演算子と、OrElse演算子が追加されている。この2つの演算子は、ショートサーキット演算子と呼ばれる。使わなくてもプログラムは作成可能だが、うまく使えば処理速度を向上できる可能性がある。C/C++/Java/C#をご存じの方は、「&&」や「||」に相当するものだといえばすぐに分かるだろう。まず、VB 6で、普通にOrとAndを使用したサンプル・プログラムを見ていただきたい(リスト4-14)。

 1: Private Function DummySearch(ByVal val As Boolean) As Boolean
 2:   Debug.Print "時間のかかる検索処理を行っています。"
 3:   DummySearch = val
 4: End Function
 5:
 6: Private Sub Form_Load()
 7:   If DummySearch(False) And DummySearch(True) Then
 8:     Debug.Print "第1の条件は満たされています。"
 9:   Else
10:     Debug.Print "第1の条件は満たされていません。"
11:   End If
12:   If DummySearch(True) Or DummySearch(False) Then
13:     Debug.Print "第2の条件は満たされています。"
14:   Else
15:     Debug.Print "第2の条件は満たされていません。"
16:   End If
17: End Sub
リスト4-14 OrとAndを使用したプログラム

 これを実行すると以下のようになる。なお“時間のかかる検索処理”は、実際には行われていないが、それが行われていると想像していただきたい。

1: 時間のかかる検索処理を行っています。
2: 時間のかかる検索処理を行っています。
3: 第1の条件は満たされていません。
4: 時間のかかる検索処理を行っています。
5: 時間のかかる検索処理を行っています。
6: 第2の条件は満たされています。
リスト4-15 リスト4-14の実行結果

 さて、これをVB.NETで表現したのがリスト4-16である。そのままAndとOrを使っても動作するが、ここではAndAlsoとOrElseに置き換えてみた。

 1: Private Function DummySearch(ByVal val As Boolean) As Boolean
 2:   Trace.WriteLine("時間のかかる検索処理を行っています。")
 3:   DummySearch = val
 4: End Function
 5:
 6: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
 7:   If DummySearch(False) AndAlso DummySearch(True) Then
 8:     Trace.WriteLine("第1の条件は満たされています。")
 9:   Else
10:     Trace.WriteLine("第1の条件は満たされていません。")
11:   End If
12:   If DummySearch(True) OrElse DummySearch(False) Then
13:     Trace.WriteLine("第2の条件は満たされています。")
14:   Else
15:     Trace.WriteLine("第2の条件は満たされていません。")
16:   End If
17: End Sub
リスト4-16 AndAlsoとOrElseを使用したVB.NETのプログラム

 これを実行すると以下のようになる。

1: 時間のかかる検索処理を行っています。
2: 第1の条件は満たされていません。
3: 時間のかかる検索処理を行っています。
4: 第2の条件は満たされています。
リスト4-17 リスト4-16の実行結果

 見て分かるとおり、VB 6のサンプルでは検索を4回行っているが、VB.NETサンプルでは2回しか検索を行っていない。これは、演算子の手前の式を計算するだけで結果が決まってしまう場合、演算子の後ろの式は計算しないという機能によるものだ。例えば「条件A Or 条件B」というとき、条件AがTrueなら、条件BがTrueでもFalseでも、式全体は必ずTrueになるので、条件Bの計算を省いても条件判断の結果は同じである。同様に「条件A And 条件B」というとき、条件AがFalseなら、条件BがTrueでもFalseでも、式全体は必ずFalseになり、条件Bの計算を省くことができる。必要な計算を減らすことで、うまく活用すれば性能アップになる。

 しかし、副作用を期待した計算式を使う場合は要注意である。副作用とは、値を計算するほかに行われる、変数の値を書き換えるなどの動作をいう。例えば、このサンプル・プログラムでいえば、文字列を出力することが副作用である。AndとOrをAndAlsoとOrElseに置き換えると、計算されない式に含まれる副作用は発生しなくなるため、動作が変わってしまう。AndとOrをAndAlsoとOrElseに書き換える場合は、式に副作用が含まれているか、よくチェックしよう。

名前に$が付く文字列関連関数と付かない関数

 VB 6には、文字列関連の関数に2つのバージョンを持つものがあった。例えば、Chr関数とChr$関数は別個の関数である。“$”の付くものは文字列型を扱い、“$”の付かないものはVariant型を扱う。この結果、文字列ではないデータを扱ったときに挙動が異なる場合があった。リスト4-18はこのような関数の一例として、Left関数とLeft$関数を扱った例である。

1: Private Sub Form_Load()
2:   Dim v As Variant, r As Variant
3:   v = Null
4:   r = Left(v, 3)
5:   Debug.Print TypeName(r)
6:   v = "ABCDEF"
7:   r = Left$(v, 3)
8:   Debug.Print TypeName(r)
9: End Sub
リスト4-18 Left関数とLeft$関数を使用したプログラム

 これを実行すると以下のようになる。

Null
String
リスト4-19 リスト4-18の実行結果

 Left関数にNull値を渡すことは合法で、結果はNull値になる。しかし、Left$関数にNull値を渡すことはできない。

 これをVB.NET用に書き換えたのがリスト4-20である。

1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2:   Dim v As Object, r As Object
3:   v = Nothing
4:   r = Microsoft.VisualBasic.Left(v, 3)
5:   Trace.WriteLine(TypeName(r))
6:   v = "ABCDEF"
7:   r = Microsoft.VisualBasic.Left$(v, 3)
8:   Trace.WriteLine(TypeName(r))
9: End Sub
リスト4-20 リスト4-18をVB.NETで書き換えたプログラム

 これを実行すると以下のようになる。

String
String
リスト4-21 リスト4-20の実行結果

 VariantがObjectになる理由については、VariantとObjectを参照してほしい。NullがNothingになるのは、VB 6からVB.NETへの構文の変更点である。さて肝心の結果だが、VB 6の場合とは異なっていることが分かるだろう。VB 6では2種類あった文字列関数は、VB.NETでは1種類しか存在しない。Variant型を返す関数は存在しないため、Left関数の結果は常に文字列になる。構文的にLeftのほかにLeft$という名前を記述することは可能だが、これは型指定文字としての$記号が付加されているだけで、別の関数の呼び出しになるわけではない(なお、Leftというキーワードのプロパティなどがあり、紛らわしい場合は、このサンプル・ソースのように、Leftの代わりにMicrosoft.VisualBasic.Leftといった長い完全修飾名の記述が必要となる場合がある。長い完全修飾名は、クラス・ライブラリのリファレンスを引くことで知ることができる)。その結果、Null(Nothing)値を引数にとった場合のLeft関数の挙動に相違が生じているわけである。文字列関連関数で、文字列以外の値を扱うことはめったにないかもしれないが、意図しないバグにより、それを処理してしまっている可能性もある。もし、VB.NETでプログラミングしていて、文字列関連の挙動がVB 6と異なるときは、チェックしてみる価値があるだろう。End of Article

VB6プログラマーのための入門 Visual Basic .NET 独習講座』

 本記事は、(株)技術評論社が発行する書籍『VB6 プログラマーのための 入門 Visual Basic .NET 独習講座』から
許可を得て転載したものです。

【本連載と書籍の関係について 】
 この書籍は、本フォーラムで連載した「連載 プロフェッショナルVB.NETプログラミング」を大幅に加筆修正し、発行されたものです。技術評論社、および著者である川俣晶氏のご好意により、書籍の内容を本フォーラムの連載記事として掲載させていただけることになりました。

技術評論社の解説ページ

ご注文はこちらから
 

 INDEX
  [連載] 改訂版 プロフェッショナルVB.NETプログラミング
  Chapter 04 演算子と関数の変化
    1.関数がクラス・ライブラリ利用に変わる/B系とW系の文字列関数
  2.Eqv演算子とImp演算子/AndAlso演算子とOrElse演算子/名前に$が付く文字列関連関数と付かない関数
 
「改訂版 プロフェッショナル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メールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH