二つのオブジェクトが同じものか調べたり、Nothingかどうか調べるにはIs演算子を使います。 オブジェクトの型を調べるにはTypeOf演算子を使います。 VB8から導入されたIsNot演算子を使うと、Not x Is Nothing
といった条件式をx IsNot Nothing
と記述することができます。
Is演算子
Is演算子はオブジェクトを比較するための演算子です。 Is演算子は、二つのオブジェクト変数を比較してそれらが同一のオブジェクトを参照しているかどうかを調べます。 同一のオブジェクトであればTrue、異なるオブジェクトであればFalseがIs演算子の結果となります。
Dim a As New List(Of Integer)
Dim b As New List(Of Integer)
Dim c As List(Of Integer) = a
If a Is b Then Console.WriteLine("a と b は同じオブジェクトです") ' このメッセージは表示されない
If a Is c Then Console.WriteLine("a と c は同じオブジェクトです") ' このメッセージは表示される
Dim r As Boolean
r = a Is a ' r = True
r = a Is b ' r = False
r = a Is c ' r = True
r = b Is c ' r = False
この例において変数aと変数bには異なるインスタンス(オブジェクト)が代入されているため、a Is b
はFalseとなります。 一方、変数cには変数aの参照が代入されていて、どちらも同一のインスタンスを参照しているため、a Is c
はTrueとなります。
参照型の変数になにも代入されていない(ヌル参照)かどうかを調べる場合にも、Is演算子を使います。 この場合、Is演算子とともにヌル参照を表すキーワードNothingを使います。
Dim a As New List(Of Integer)
Dim b As List(Of Integer) = Nothing
If a Is Nothing Then Console.WriteLine("a は Nothingです") ' このメッセージは表示されない
If b Is Nothing Then Console.WriteLine("b は Nothingです") ' このメッセージは表示される
Dim r As Boolean
r = a Is Nothing ' r = False
r = b Is Nothing ' r = True
=演算子をオブジェクトの比較に使うことはできません。 =演算子は値が同値・等価かどうかの比較を行います。 対してIs演算子は参照が同一かどうかの比較を行います。
Dim a As New List(Of Integer)
Dim b As List(Of Integer) = Nothing
' =演算子を使って次のような比較を行うことはできない
If a = b Then Console.WriteLine("a と b は同一です")
If b = Nothing Then Console.WriteLine("b は Nothingです")
IsNot演算子
Is演算子を使うケースとして一番多く挙げられるのはNothingでないかどうかのチェック、つまり次の例のようなヌル判定です。
Dim s As String = "foo"
' sがNothingでない場合、文字列の末尾に"bar"を加える
If Not s Is Nothing Then s += "bar"
Is演算子を使って変数がNothingではないかどうか評価する場合、If Not x Is Nothing Then ...
のようにIs演算子の結果をNot演算子で反転することになります。 C#ではヌル判定に==演算子・!=演算子を使うことができるので記述が長くなることはありませんが、VBでは先に述べたように=演算子・<>演算子によるヌル判定はできないため、このような長い条件式を何度も入力することが多く不便でした。
VB8(VB2005)からはこの不便を解消するIsNot演算子が導入されました。 IsNot演算子を使うことにより、ヌル判定の条件式はIf x IsNot Nothing Then ...
と記述することができるようになります。 Not演算子を条件式の先頭に記述する必要がなくなるため、読みやすさも向上します。
Dim s As String = "foo"
' sがNothingでない場合、文字列の末尾に"bar"を加える
If s IsNot Nothing Then s += "bar"
IsNot演算子は、Is演算子の結果を否定(Not)したものと同じです。 またヌル判定だけでなく、Is演算子と同様に二つの変数が同一のオブジェクトではないかどうかを調べることもできます。
Dim a As New List(Of Integer)
Dim b As New List(Of Integer)
Dim c As List(Of Integer) = a
If a Is b Then Console.WriteLine("a と b は同じオブジェクトです") ' このメッセージは表示されない
If a IsNot b Then Console.WriteLine("a と b は異なるオブジェクトです") ' このメッセージは表示される
If a Is c Then Console.WriteLine("a と c は同じオブジェクトです") ' このメッセージは表示される
If a IsNot c Then Console.WriteLine("a と c は異なるオブジェクトです") ' このメッセージは表示されない
Dim r As Boolean
r = a IsNot a ' r = False
r = a IsNot b ' r = True
r = a IsNot c ' r = False
r = b IsNot c ' r = True
TypeOf演算子
TypeOf演算子は、オブジェクトがある型かどうかを比較するための演算子です。 TypeOf演算子は常にIsを伴い、TypeOf 変数 Is 型
のように使います。 TypeOf演算子は、C#におけるis演算子に相当するものです。
Dim o As Object = "foo"
If TypeOf o Is String Then Console.WriteLine("o は String です") ' このメッセージは表示される
o = New List(Of Integer)
If TypeOf o Is String Then Console.WriteLine("o は String です") ' このメッセージは表示されない
If TypeOf o Is List(Of Integer) Then Console.WriteLine("o は List(Of Integer) です") ' このメッセージは表示される
If TypeOf o Is List(Of String) Then Console.WriteLine("o は List(Of String) です") ' このメッセージは表示されない
このように、TypeOf演算子を使うことで変数に格納されているオブジェクトの型を調べることができます。 そのため、実行時まで変数にどのような型のオブジェクトが設定されるか分からない場合などにTypeOf演算子を使って処理を場合分けすることができます。
このように、TypeOf演算子を使うことで型による場合分けができますが、型による場合分けをしたあと多くの場合はその型へのキャストを行うこととなります。 その際にはDirectCast演算子およびTryCast演算子を使うことができます。
なお、TypeOf演算子ではIsの代わりとしてIsNotを使うことはできません。 従って、オブジェクトがある型ではないかどうかを調べるには次のようにNot演算子を使う必要があります。
Dim o As Object = 16
If Not TypeOf o Is Double Then Console.WriteLine("o は Double ではありません") ' このメッセージは表示される
If Not TypeOf o Is Integer Then Console.WriteLine("o は Integer ではありません") ' このメッセージは表示されない
' このように記述することはできない
'If TypeOf o IsNot Double Then Console.WriteLine("o は Double ではありません")
'If TypeOf o IsNot Integer Then Console.WriteLine("o は Integer ではありません")
このほかにも、TypeOf演算子を使うことにより、型があるクラスを継承しているか、インターフェイスを実装しているかどうか、といったことを調べることもできます。
Dim l As New List(Of Integer)
If TypeOf l Is ICloneable Then
Console.WriteLine("ICloneableインターフェイスを実装しています")
End If
If TypeOf l Is IEnumerable(Of Integer) Then
Console.WriteLine("IEnumerable(Of Integer)インターフェイスを実装しています")
End If
TypeOf演算子と継承関係・インターフェイスについて詳しくはインスタンスや型が一致するか・インターフェイスやクラスから派生しているか判定するで解説しています