PowerShellパイプラインの戻り値の型について

コンピュータ
PowerShellのあれこれ

PowerShellで以下のコードを実行すると結果は何になるでしょう?

PS>(1,2,3).GetType()

結果は配列(System.Array)で具体的にはObject[]ということでオブジェクト型の配列となります。
実際配列の要素は数値を設定してあるので整数型のInt型になるかと思いましたが、大概のオブジェクトの祖であるObjectの配列となっています。数値型もObjectから派生しているのでObject[]の配列の要素となることが出来ます。

配列を?(Where-Object)で要素を絞り込んでみます。

PS>(1,2,3) | ? { $_ -lt 3}
1
2

3より小さな値で絞り込むと1と2が結果として戻ります。

さてこの結果の型は何になるでしょう?

PS>((1,2,3) | ? { $_ -lt 3}).GetType()

先ほどと同様にObject型の配列が戻ります。

次に絞り込み条件を2より小さな値で実行してみます。

PS>(1,2,3) | ? { $_ -lt 2}
1

結果1が戻ります。この型を確認してみます。

PS>((1,2,3) | ? { $_ -lt 2}).GetType()

先ほどと異なりSystem.ValueTypeが戻ります。配列(System.Array)ではなく値型(System.ValueType)です。
具体的にはInt32ですので整数値になります。先ほどがこちらがObject型でした。

さらに絞り込み条件を変えてみます。

PS>(1,2,3) | ? { $_ -lt 1}

1より小さな値は存在しないので何も返ってこないようです。
では型を確認しようかと思いますが、何も返ってこないとことで$Nullと比較してみます。

PS>((1,2,3) | ? { $_ -lt 1}) -eq $Null
True

まとめると、パイプラインの戻り値が複数ある場合、配列(System.Array)が返り、1件の場合、値型(System.ValueType)が返り、0件(無い)の場合$Nullが返ります。

型を意識することなくプログラミング出来るのがPowerShellの良さですが、逆にいうと、「この処理でこの変数はこの型であろう」と期待すると裏切られるかもしれません。

ちなみに同じ.NetFrameworkのオブジェクトを扱えるC#のLINQとPowerShellのパイプラインを同時学習すると、似ているようで異なりますので、どうしてこのように作ったか想像してみるのも面白いです。

コメント