PowerShellは一癖ある言語で、文法が少し違うのため戸惑う事が多いです。関数に参照渡しの引数を使うのも一苦労。
新しい言語ではこういう基本的なところではまってしまうんですよね。
STEP1
参照に ref をつけるのは、C#等と同じ概念です。こんな感じでコールすると
Function fnc([int]$x, [int]$y, [ref][int]$w, [ref][int]$z) { if($y -ne 0) { $w = $x / $y $z = $x * $y Return $true } else { Return $false } } [int]$z = 0 [int]$w = 0 [Boolean]$ret = fnc 10 5 [ref]$w [ref]$z $ret $w $z
実行結果
fnc : パラメーター 'w' の引数変換を処理できません。値 "[ref]0" を型 "System.Int32" に変換できません。エラー: "入力文字列の形式が正しくありません。" 発生場所 C:\temp\test.ps1:19 文字:26 + [Boolean]$ret = fnc 10 5 [ref]$w [ref]$z + ~~~~~~~ + CategoryInfo : InvalidData: (:) [fnc]、ParameterBindingArgumentTransformationException + FullyQualifiedErrorId : ParameterArgumentTransformationError,fnc
呼び出し方に問題があるようです。
STEP2
規則1: 引数の参照渡し時には丸括弧で囲む 例: ([ref]$w)
注意点は fnc( 10, 5, [ref]$w, [ref]$z) ではなく、fnc 10 5 ([ref]$w) ([ref]$z) と引数1つ1つを括弧で括ることです。あと、引数の区切りはスペースであり、カンマではない点も注意してください。関数の定義はカンマを使っているのに呼び出し時は使ってはいけないというのは違和感を感じますが、慣れるしかありません。
では、実行してみましよう。
Function fnc([int]$x, [int]$y, [ref][int]$w, [ref][int]$z) { if($y -ne 0) { $w = $x / $y $z = $x * $y Return $true } else { Return $false } } [int]$z = 0 [int]$w = 0 [Boolean]$ret = fnc 10 5 ([ref]$w) ([ref]$z) $ret $w $z
実行結果
True 0 0
あれ、エラーにならないのに値が入らない。参照しているはずなのに。。。
初めて遭遇したときは謎の仕様に使うのを諦めてしまいました・・・
こういう所でつまづくとやる気を無くしてしまいますね。
STEP3
規則2: 参照した引数に値をセットするときは、Valueプロパティを使う。例: $w.Value = 10
違和感ありあり。[ref][int]$w なのでint型なのに、Valueプロパティなんてあるの ?
それがあるんですよ。$w.GetType() で型情報を調べてみると・・・
$w.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Int32 System.ValueType
このようにobjectなんですよ。そして、Value というプロパティがあります。では、気を取り直して以下を実行してみます。
Function fnc([int]$x, [int]$y, [ref][int]$w, [ref][int]$z) { if($y -ne 0) { $w.Value = $x / $y $z.Value = $x * $y Return $true } else { Return $false } } [int]$z = 0 [int]$w = 0 [Boolean]$ret = fnc 10 5 ([ref]$w) ([ref]$z) $ret $w $z
実行結果
True 2 50
やっとうまくいきました。サンプルで試すと理解できます。