型演算子

これまで演算子として算術演算子、代入演算子、比較演算子、リダイレクト演算子を取り上げてきた。演算子はプログラミング言語要素のひとつで、値を操作しやすくするために提供される機能だ。PowerShell Coreは演算子の種類が多く、さまざまな処理がサポートされている。

PowerShell Coreで提供されている演算子のひとつに型演算子というものがある。演算子の数自体は少ないのだが、特徴的な機能であり本格的にコーディングに取り組む際には知っておきたい機能だ。次の3つが用意されている。

演算子 内容
-is 指定された対象が指定された.NETの型だった場合にTrue、そうでない場合にFalseを返す
-isNot 指定された対象が指定された.NETの型ではなかった場合にTrue、そうでない場合にFalseを返す
-as 指定された対象が指定された.NETの型に変換を試み成功した場合に変換後の対象を、そうでない場合に$nullを返す

オブジェクトの型を判定するための演算子が提供されているプログラミング言語は多い。PowerShell Coreの場合は-isがそれだ。比較対象となる型は.NET Frameworkの型となる。

PowerShell Coreで興味深いのは-isと逆の結果を返す-isNotが用意されている点と、キャストに相当する処理が演算子-asとして提供されている点にある。-asは指定された型への変換を試み、失敗した場合には結果として$nullを返す。処理が例外やエラーを発生するというものではなく、変換できなかった場合には$nullが返る仕様になっている。

型判定を行う-isの反対の意味を持つ-isNotは、記述の通り英語のシンタックスがそのままPowerShell Coreの言語仕様になったものだ。PowerShell Coreはこのような仕様が多く、-isNotもそれに習っていることがわかる。否定を併用すれば-isだけで事足りるが、演算子として-isNotが用意されている。

型演算子はオブジェクトを左に、演算子を真ん中に、型を右に配置するといったように順序が決まっており、次のように記述する。型は[]で囲む必要がある。

型演算子の記述順序

オブジェクト 型演算子 [.NET型]

または、次のように[]ではなく”“で囲って記述することもできる。

型演算子の記述順序

オブジェクト 型演算子 ".NET型"

型演算子の使用例を挙げると次のようになる。

型演算子の仕様例

PS /Users/daichi> (get-date) -is [DateTime]
True
PS /Users/daichi> (get-date) -is "DateTime"
True
PS /Users/daichi> (get-date) -isNot [DateTime]
False
PS /Users/daichi> (get-date) -isNot "DateTime"
False
PS /Users/daichi> "5/7/07" -as [DateTime]

2005年7月7日 木曜日 0:00:00

PS /Users/daichi> "5/7/07/09/01" -as [DateTime]
PS /Users/daichi>

.NET Frameworkの型は名前空間のルートに存在するものに対しては[DateTime]や”DateTime”のように名前だけで記述できる。そうでない場合には[System.Diagnostics.Process]のようにフルパスで指定する必要がある。ただし、System.に関しては省略してもよいことになっているので、[Diagnostics.Process]または”Diagnostics.Process”のように記述することになる。

継承の関係にあるクラスに対して-isや-isNotでチェックを行った場合、それは一致の対象となる。たとえば次のサンプルを見るとわかるように、Get-Item /の結果はSystem.IO.FileSystemInfoが基本の型として判断されているが、System.IO.DirectoryInfoと比較してもTrueが返ってきている。

継承関係にあるものは一致の対象になる

PS /Users/daichi> (Get-Item /).GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    DirectoryInfo                            System.IO.FileSystemInfo

PS /Users/daichi> (Get-Item /) -is [System.IO.FileSystemInfo]
True
PS /Users/daichi> (Get-Item /) -is [System.IO.DirectoryInfo]
True
PS /Users/daichi>

次のようにSystem.IO.DirectoryInfoはSystem.IO.FileSystemInfoを親として持っていることがわかる。継承関係にあることになる。

System.IO.DirectoryInfoはSystem.IO.FileSystemInfoを継承している

PS /Users/daichi> [System.IO.FileSystemInfo].GetTypeInfo()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    FileSystemInfo                           System.MarshalByRefObject

PS /Users/daichi> [System.IO.DirectoryInfo].GetTypeInfo()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    DirectoryInfo                            System.IO.FileSystemInfo

PS /Users/daichi>

なお、PowerShell Coreでは対象がコレクションだった場合にはコレクションの中身を取り出して処理したりといったことがあるのだが、型演算子についてはコレクションそのものが評価の対象となる。コレクションはコレクションとして比較の対象となる。

型演算子の実行例

型演算子を使用すると、たとえば入力されたデータであるとかファイルに書き込まれていたデータが特定の型、たとえば整数であるとか、日付であるとか、そういった型に沿った形式になっているかどうかを調べることができる。

型演算子の実行例

PS /Users/daichi> 32 -is [Float]
False
PS /Users/daichi> 32 -is "int"
True
PS /Users/daichi> (Get-Date) -is [DateTime]
True
PS /Users/daichi> "12/31/2007" -is [DateTime]
False
PS /Users/daichi> "12/31/2007" -is [String]
True
PS /Users/daichi> (Get-Process pwsh)[0] -is [System.Diagnostics.Process]
True
PS /Users/daichi> (Get-Command get-member) -is [System.Management.Automation.CmdletInfo]
True
PS /Users/daichi>

PowerShell Coreではパイプを流れるデータはテキストデータではなくオブジェクトデータになっている。型演算子を使うと、流れてくるオブジェクトの種類に応じて処理を変えるといったことができるようになる。

型演算子の実行例

PS /Users/daichi> (Get-Culture) -is [System.Globalization.CultureInfo]
True
PS /Users/daichi> (Get-UICulture) -is [System.Globalization.CultureInfo]
True
PS /Users/daichi> (Get-Culture), (Get-UICulture) -is [System.Globalization.CultureInfo]
False
PS /Users/daichi> (Get-Culture), (Get-UICulture) -is [Array]
True
PS /Users/daichi> (get-culture), (get-uiculture) -is [Object]
True
PS /Users/daichi> (Get-Culture), (Get-UICulture) -is [Object]
True
PS /Users/daichi>

型キャスト演算子となる-asは一見すると適切なデータ形式のように見えても、曖昧な場合にはキャストができない。たとえば次の例は”12/31/07”を変換しているが、ロケールによっては曖昧なデータ形式であり変換は行われない。

型演算子の実行例

PS /Users/daichi> "12/31/07" -is [DateTime]
False
PS /Users/daichi> "12/31/07" -as [DateTime]
PS /Users/daichi> "12/31/2007" -as [DateTime]

2007年12月31日 月曜日 0:00:00

PS /Users/daichi> "12/31/2007" -is [DateTime]
False
PS /Users/daichi> 1031 -as [System.Globalization.CultureInfo]

LCID             Name             DisplayName
----             ----             -----------
1031             de-DE            ドイツ語(ドイツ)

PS /Users/daichi>

型まで意識したコーディングをするようになるとかなりプログラミング言語的な要素が強くなってくる。本連載の目的を考えると型まで判定するような処理を行うことはあまり発生しないが、型演算子が使われているコードを読むことはあるだろう。どういった機能であるかは把握しておこう。

参考資料