この記事は、PowerShell 5.1で実行した結果をもとにしています。
動機
普段はC#で書いているのですが、諸処事情により「ここはPowerShellの出番かな」と思ったので書き始めたところ、usingステートメントがないってことで「じゃぁフィルターみたいな関数を書けばいいのかな」と思い立ち、「パイプラインで複数段つなげると、beginとかendが呼ばれる順番って、どうなるんだろう」となったわけです。
作ってみた
ということで、こんなスクリプトを書いてみました。
function Filter-A {
param(
[Parameter(Mandatory, Position = 0, ValueFromPipeline)]
[string] $str
)
begin {
echo "begin A"
}
process {
$str + "A"
}
end {
echo "end A"
}
}
function Filter-B {
param(
[Parameter(Mandatory, Position = 0, ValueFromPipeline)]
[string] $str
)
begin {
echo "begin B"
}
process {
$str + "B"
}
end {
echo "end B"
}
}
1..5 | Filter-A | Filter-B
実行してみた
実行してみたところ、こんな結果になりました。
PS > .¥filter_test.ps1
begin B
begin AB
1AB
2AB
3AB
4AB
5AB
end AB
end B
begin B
begin AB
やってしまいました。Filter-Aのbeginがecho "begin A"
しているので、それをFilter-Bが受け取って、Filter-Bのbegin実行後、Filter-Bのprocessで$str + "B"
してしまっています。
1AB
ここから5行は予定通りですね。
end AB
これって、出力しているのはFilter-Bのprocessですね。ということは、Filter-Aのendで実行されたecho "end A"
をFilter-Bが受け取って処理し、その後にFilter-Bのendが実行されているということです。
まとめ
ということで、パイプラインでは先頭から順番にbeginが実行され、先頭から順番にendも実行されていました。
つまり、C#のusingステートメントをネストした場合とはendの呼ばれる順番が逆になるので、そのままでは代替にならない(場合もある)ということでした。
ぐぬぬ。。。