2013-08-08T00:49:49の更新内容

programming/vb.net/operator_is_isnot_typeof/index.wiki.txt

current previous
1,148 1,75
~
${smdncms:title,Is演算子・IsNot演算子・TypeOf演算子}
${smdncms:title,IsNot演算子}
~
${smdncms:keywords,Is,IsNot,TypeOf,演算子,Nothing,ヌル判定,ヌル比較,型判定,型比較,オブジェクト参照,型情報}
${smdncms:keywords,IsNot}
 
${smdncms:meta,toc-amazonlivelink-keyword,books-jp,visual basic}
${smdncms:meta,toc-amazonlivelink-keyword,books-jp,visual basic}
-
#navi(..)
-
VB.NET(VB7.x)では参照型変数の比較にIs演算子を使用していました。 例えば変数aがNothing(null)であるかをチェックするには「If a Is Nothing ~」としていました。 C#の==演算子、!=演算子のように=演算子や<>演算子で比較できれば良かったのですが、VB.NETではIs演算子を使わなければならないため、仮に、Nothingではないことをチェックする場合には、わざわざ「If Not a Is Nothing Then ~」としなければなりませんでした。
 

        

        
~
二つのオブジェクトが同じものか調べたり、Nothingかどうか調べるには[[Is演算子>#IsOperator]]を使います。 オブジェクトの型を調べるには[[TypeOf演算子>#TypeOfOperator]]を使います。 VB8から導入された[[IsNot演算子>#IsNotOperator]]を使うと、``Not &var{x}; Is Nothing``といった条件式を``&var{x}; IsNot Nothing``と記述することができます。
しかし、VB8ではIsNot演算子が追加されたので、Nothingではないという評価をしたい場合は「If a IsNot Nothing Then ~」と記述出来るようになりました。
~

          
#googleadunit
+
-関連するページ
+
--[[programming/vb.net/operator_directcast_trycast]]
+
--[[programming/netfx/tips/check_type_isassignablefrom_issubclassof]]
+
--[[programming/vb.net/basics/02_operator]]
+

          
+
#googleadunit(banner)
+

          
+
*Is演算子 [#IsOperator]
+
Is演算子はオブジェクトを比較するための演算子です。 Is演算子は、二つのオブジェクト変数を比較してそれらが同一のオブジェクトを参照しているかどうかを調べます。 同一のオブジェクトであればTrue、異なるオブジェクトであればFalseがIs演算子の結果となります。
 

        

        
 
#code(vb){{
#code(vb){{
~
Dim a As New List(Of Integer)
Imports System
+
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となります。
Class T : End Class
 

        

        
~
参照型の変数になにも代入されていない(ヌル参照)かどうかを調べる場合にも、Is演算子を使います。 この場合、Is演算子とともにヌル参照を表すキーワードNothingを使います。
Class IsNotOperatorSample
 

        

        
~
#code(vb){{
    Public Shared Sub Main()
+
Dim a As New List(Of Integer)
+
Dim b As List(Of Integer) = Nothing
 

        

        
~
If a Is Nothing Then Console.WriteLine("a は Nothingです") ' このメッセージは表示されない
        Dim instance As T
+
If b Is Nothing Then Console.WriteLine("b は Nothingです") ' このメッセージは表示される
 

        

        
~
Dim r As Boolean
        instance = New T
 

        

        
~
r = a Is Nothing ' r = False
        If instance Is Nothing Then Console.WriteLine("'instance' is nothing.")
~
r = b Is Nothing ' r = True
        If instance IsNot Nothing Then Console.WriteLine("'instance' is not nothing.")
+
}}
 

        

        
~
=演算子をオブジェクトの比較に使うことはできません。 =演算子は''値が同値・等価かどうか''の比較を行います。 対してIs演算子は''参照が同一かどうか''の比較を行います。
        instance = Nothing
 

        

        
~
#code(vb){{
        If instance Is Nothing Then Console.WriteLine("'instance' is nothing.")
~
Dim a As New List(Of Integer)
        If instance IsNot Nothing Then Console.WriteLine("'instance' is not nothing.")
+
Dim b As List(Of Integer) = Nothing
+

          
+
' =演算子を使って次のような比較を行うことはできない
+
If a = b Then Console.WriteLine("a と b は同一です")
+
If b = Nothing Then Console.WriteLine("b は Nothingです")
+
}}
 

        

        
~
*IsNot演算子 [#IsNotOperator]
    End Sub
+
Is演算子を使うケースとして一番多く挙げられるのは''Nothingでないかどうか''のチェック、つまり次の例のようなヌル判定です。
+

          
+
#code(vb){{
+
Dim s As String = "foo"
 

        

        
~
' sがNothingでない場合、文字列の末尾に"bar"を加える
End Class
+
If Not s Is Nothing Then s += "bar"
 
}}
}}
 

        

        
~
Is演算子を使って変数がNothingではないかどうか評価する場合、``If Not &var{x}; Is Nothing Then ...``のようにIs演算子の結果をNot演算子で反転することになります。 C#ではヌル判定に==演算子・!=演算子を使うことができるので記述が長くなることはありませんが、VBでは先に述べたように=演算子・<>演算子によるヌル判定はできないため、このような長い条件式を何度も入力することが多く不便でした。
#prompt(実行結果){{
~

          
'instance' is not nothing.
~
VB8(VB2005)からはこの不便を解消するIsNot演算子が導入されました。 IsNot演算子を使うことにより、ヌル判定の条件式は``If &var{x}; IsNot Nothing Then ...``と記述することができるようになります。 Not演算子を条件式の先頭に記述する必要がなくなるため、読みやすさも向上します。
'instance' is nothing.
+

          
+
#code(vb){{
+
Dim s As String = "foo"
+

          
+
' sがNothingでない場合、文字列の末尾に"bar"を加える
+
If s IsNot Nothing Then s += "bar"
 
}}
}}
 

        

        
~
IsNot演算子は、Is演算子の結果を否定(Not)したものと同じです。 またヌル判定だけでなく、Is演算子と同様に二つの変数が同一のオブジェクト''ではない''かどうかを調べることもできます。
またIs演算子同様、IsNot演算子で二つの変数が同一のインスタンスを参照しているか否かをチェックすることも出来ます。
 

        

        
 
#code(vb){{
#code(vb){{
~
Dim a As New List(Of Integer)
Imports System
+
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演算子 [#TypeOfOperator]
Class T : End Class
+
TypeOf演算子は、オブジェクトがある型かどうかを比較するための演算子です。 TypeOf演算子は常にIsを伴い、``TypeOf &var{変数}; Is &var{型};``のように使います。 TypeOf演算子は、C#におけるis演算子に相当するものです。
 

        

        
~
#code(vb){{
Class IsNotOperatorSample
+
Dim o As Object = "foo"
 

        

        
~
If TypeOf o Is String Then Console.WriteLine("o は String です") ' このメッセージは表示される
    Public Shared Sub Main()
 

        

        
~
o = New List(Of Integer)
        Dim a, b As T
 

        

        
~
If TypeOf o Is String Then Console.WriteLine("o は String です") ' このメッセージは表示されない
        a = New T
~
If TypeOf o Is List(Of Integer) Then Console.WriteLine("o は List(Of Integer) です") ' このメッセージは表示される
        b = New T
+
If TypeOf o Is List(Of String) Then Console.WriteLine("o は List(Of String) です") ' このメッセージは表示されない
+
}}
+

          
+
このように、TypeOf演算子を使うことで変数に格納されているオブジェクトの型を調べることができます。 そのため、実行時まで変数にどのような型のオブジェクトが設定されるか分からない場合などにTypeOf演算子を使って処理を場合分けすることができます。
 

        

        
~
このように、TypeOf演算子を使うことで型による場合分けができますが、型による場合分けをしたあと多くの場合はその型へのキャストを行うこととなります。 その際には[[DirectCast演算子およびTryCast演算子>programming/vb.net/operator_directcast_trycast]]を使うことができます。
        If a Is b Then Console.WriteLine("same instance")
-
        If a IsNot b Then Console.WriteLine("different instance")
 

        

        
~
なお、TypeOf演算子ではIsの代わりとしてIsNotを使うことはできません。 従って、オブジェクトがある型''ではない''かどうかを調べるには次のようにNot演算子を使う必要があります。
        a = b
 

        

        
~
#code(vb){{
        If a Is b Then Console.WriteLine("same instance")
~
Dim o As Object = 16
        If a IsNot b Then Console.WriteLine("different instance")
 

        

        
~
If Not TypeOf o Is Double Then Console.WriteLine("o は Double ではありません") ' このメッセージは表示される
    End Sub
+
If Not TypeOf o Is Integer Then Console.WriteLine("o は Integer ではありません") ' このメッセージは表示されない
 

        

        
~
' このように記述することはできない
End Class
+
'If TypeOf o IsNot Double Then Console.WriteLine("o は Double ではありません")
+
'If TypeOf o IsNot Integer Then Console.WriteLine("o は Integer ではありません")
 
}}
}}
 

        

        
~
このほかにも、TypeOf演算子を使うことにより、型があるクラスを継承しているか、インターフェイスを実装しているかどうか、といったことを調べることもできます。 (TypeOf演算子と継承関係・インターフェイスについて詳しくは[[programming/netfx/tips/check_type_isassignablefrom_issubclassof]]で解説しています)
#prompt(実行結果){{
~

          
different instance
~
#code(vb,インターフェイスを実装しているか調べる例){{
same instance
+
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
 
}}
}}
 

        

        
-
#navi(..)

programming/vb.net/operator_directcast_trycast/index.wiki.txt

current previous
1,81 0,0
+
${smdncms:title,DirectCast演算子・TryCast演算子}
+
${smdncms:keywords,DirectCast,TryCast,キャスト,型変換}
+
${smdncms:meta,toc-amazonlivelink-keyword,books-jp,visual basic}
+

          
+
オブジェクトを別の型にキャストするには[[DirectCast演算子>#DirectCastOperator]]を使います。 [[TryCast演算子>#TryCastOperator]]を使うと、キャストできなかった場合でも例外をスローせずキャスト結果をNothingにすることができます。
+

          
+
-関連するページ
+
--[[programming/vb.net/operator_is_isnot_typeof]]
+
--[[programming/netfx/tips/check_type_isassignablefrom_issubclassof]]
+
--[[programming/vb.net/basics/02_operator]]
+

          
+
#googleadunit(banner)
+

          
+
*DirectCast演算子 [#DirectCastOperator]
+
DirectCast演算子はオブジェクトをある型にキャストするための演算子で、``DirectCast(&var{変数};, &var{キャスト後の型};)``というように使用します。
+

          
+
#code(vb){{
+
Dim s As Stream = ...
+

          
+
' ストリームの型を調べる
+
If TypeOf s Is MemoryStream Then
+
  ' ストリームがMemoryStreamだった場合、MemoryStreamにキャストする
+
  Dim ms As MemoryStream = DirectCast(s, MemoryStream)
+

          
+
  ' MemoryStreamに対する処理を行う
+
  ms.ToArray()
+
End If
+
}}
+

          
+
#code(vb){{
+
Sub ControlClicked(ByVal sender As Object, ByVal e As EventArgs)
+
  ' senderに格納されているオブジェクトの型を調べる
+
  If TypeOf sender Is Button Then
+
    ' Buttonにキャストする
+
    Dim b As Button = DirectCast(sender, Button)
+
  Else If TypeOf sender Is CheckBox Then
+
    ' CheckBoxにキャストする
+
    Dim c As CheckBox = DirectCast(sender, CheckBox)
+
  End If
+
End Sub
+
}}
+

          
+
互換性がない型へのキャスト、例えば継承関係にないクラスへの変換やInteger→Doubleなど異なる型へのキャストを行おうとした場合、例外&msdn(netfx,type,System.InvalidCastException){InvalidCastException};がスローされます。
+

          
+
#code(vb){{
+
Dim i As Integer = 42
+

          
+
' Integer型の値をObject型に代入
+
Dim o As Object = i
+

          
+
' Object型に格納されているIntegerの値をDoubleにキャストしようとする
+
' (実行時にInvalidCastExceptionがスローされる)
+
Dim d As Double = DirectCast(o, Double)
+
}}
+

          
+
Integer→Doubleなど異なる型への変換を行いたい場合はDirectCast演算子ではなくCType関数を使います。
+

          
+
DirectCast演算子でキャスト可能かどうかを事前に調べるには[[TypeOf演算子>programming/vb.net/operator_is_isnot_typeof#TypeOfOperator]]を使います。 TypeOf演算子で型チェックを行った結果Trueとなった場合はキャスト可能なので、DirectCast演算子でその型に変換する際に例外がスローされることはありません。
+

          
+

          
+
*TryCast演算子 [#TryCastOperator]
+
TryCast演算子はVB8(VB2005)で導入された演算子で、DirectCast演算子に似たキャストを行うための演算子ですが、DirectCastとは動作が異なります。
+

          
+
DirectCastと同様``TryCast(&var{変数};, &var{キャスト後の型};)``というように使用しますが、キャストできない場合でも例外がスローされることはありません。 代わりに、キャストできない場合にはTryCastはNothingを返します。 つまりTryCast演算子はある型へのキャストを試み、キャストできた場合はその型の値、できなかった場合はNothingを返します。
+

          
+
TryCast演算子を使う場合は、キャストできない場合でも例外はスローされないので事前にTypeOf演算子で型チェックを行う必要がなくなります。
+

          
+
#code(vb){{
+
Dim s As Stream = ...
+

          
+
' MemoryStreamへのキャストを試みる
+
Dim ms As MemoryStream = TryCast(s, MemoryStream)
+

          
+
If ms IsNot Nothing Then
+
  ' キャストできた場合、MemoryStreamに対する処理を行う
+
  ms.ToArray()
+
End If
+
}}
+

          
+
なお、TryCast演算子は参照型にのみ使用できます。 そのため構造体へのキャストなどには使うことはできません。 また、TryCast演算子はC#におけるas演算子に相当するものです。
+