[PowerShellの関数の戻り値に関する2つの問題:目次]
あー!イライラするー!💢
どしたの?
なんか全然思った通り動いてくんないんだよな!PowerShellの野郎!💢
もしかして「関数の戻り値の扱い」に苦労してる?
目次
標準出力やAddメソッドの結果が戻り値に含まれる
そう!なぜわかった!?
こんなコード書いてるんだけど、、何が悪いんだ?
function func {
$dataTable = New-Object System.Data.DataTable
$dataTable.Columns.Add("columns1")
$newRow = $dataTable.NewRow()
$newRow.columns1 = "abc"
$dataTable.Rows.Add($newRow)
Write-Output "hogehoge"
return $dataTable
}
$result = func
if($result.Rows.Count -eq 1){
Write-Output "1行だぞ"
}else{
Write-Output "1行じゃないぞ"
}
1回だけAddでRowを追加したから、1行のDataTableが戻り値になるはずなのに。
「1行じゃないぞ」の方が出力されちゃうんだよな。。
そりゃそうだよ。
PowerShellの関数の戻り値には「標準出力」とかreturnに指定したオブジェクト以外も含まれるんだよ。
どういうことなんだ!?詳しく教えてくれよおお!!
(面倒くさいなあ)
とりあえず、その$resultの中身を見てみてよ。
おお、そうだった。
デバッグの基本はプリントデバッグだな。
AllowDBNull : True
AutoIncrement : False
AutoIncrementSeed : 0
AutoIncrementStep : 1
Caption : columns1
ColumnName : columns1
Prefix :
DataType : System.String
DateTimeMode : UnspecifiedLocal
DefaultValue :
Expression :
ExtendedProperties : {}
MaxLength : -1
Namespace :
Ordinal : 0
ReadOnly : False
Table : {System.Data.DataRow}
Unique : False
ColumnMapping : Element
Site :
Container :
DesignMode : False
hogehoge
columns1 : abc
思ってたのと全然違う!!!
$resultのカウントと型も見てみてよ。
こうか?
> $result.Count
3
> $result.GetType()
IsPublic IsSerial Name BaseType
——– ——– —- ——–
True True Object[] System.Array
型名が「Object[]」でカウント「3」?
DataTableが1つ返ってきてるだけじゃないみたいだな。
returnで指定したDataTable以外に2つが戻り値に含まれてるのが分かるよね。
hogehogeと、何かよく分からんデカいオブジェクトが余計だな!!
そう。よく分からんデカいオブジェクトはAddメソッドの結果だよ。それも戻り値に含まれるんだ。
意味不明だな!!!
PowerShell関数の戻り値に含まれるもの
- returnに指定したオブジェクト
- 標準出力の結果
- Addメソッドの結果
戻り値に含みたくない場合はどうすればいいんだ!?
教えてくれよ!!!
パイプ(|)で繋いで「Out-Null」を付ければいいんだよ。
たったそれだけでいいのか!!
こうか?
function func {
$dataTable = New-Object System.Data.DataTable
$dataTable.Columns.Add("columns1") | Out-Null
$newRow = $dataTable.NewRow()
$newRow.columns1 = "abc"
$dataTable.Rows.Add($newRow)
Write-Output "hogehoge" | Out-Null
return $dataTable
}
$result = func
if($result.Rows.Count -eq 1){
Write-Output "1行だぞ"
}else{
Write-Output "1行じゃないぞ"
}
とりあえずOK。$resultを見たら欲しいものだけになってるはずだよ。でもあともう一個直さないと・・・
>>$result
columns1
————–
abc
おーう!できたできた!!これこれ!!
DataTableの行数によって戻り値の型が異なる
ん?まだオカシイ!やっぱり出力結果が
「 1行じゃないぞ 」になるじゃねえか!
(話を最後まで聞いてよ)
型を見てみてよ。
>>$result.GetType()
IsPublic IsSerial Name BaseType
——– ——– —- ——–
True False DataRow System.Object
DataRowになってる!!
そりゃDataRowに対してRowsを取ろうとしてもそんなものは無いからな・・・でもエラーにはならないのか!
戻り値がDataTable1つだけだった場合、DataTableが2行以上なら「Object[]」、1行なら「DataRow」、0行なら「null」として返されるんだ。
意味不明だな!!!
関数の戻り値がDataTableだけの場合
- 2行以上なら「Object[]」として返される
- 1行なら「DataRow」として返される
- 0行なら「null」として返される
2行以上のときはGetType()でObjectになっていることを確認できるけど、実体としてはDataTableだから、この時だけは山田君の書き方が有効なんだ。
➡$result.Rows.Count
クソ面倒くさいけど分かったぞ!
つまり行数の判断の前に、型の判断をワンクッション挟めばいいんだな!
function func {
$dataTable = New-Object System.Data.DataTable
$dataTable.Columns.Add("columns1") | Out-Null
$newRow = $dataTable.NewRow()
$newRow.columns1 = "abc"
$dataTable.Rows.Add($newRow)
return $dataTable
}
$result = func
if($result.GetType().Name -eq "DataRow")
{
Write-Output "1行だぞ"
}
elseif($result -eq $null)
{
Write-Output "0行だぞ"
}
elseif($result.Rows.Count -gt 1)
{
$message = $result.Rows.Count.ToString() + "行だぞ"
Write-Output $message
}
else
{
Write-Output "不明だぞ"
}
よし!「1行だぞ」になった!
ついでに2行以上のときはちゃんと行数も出力してくれるようにしといた!
やっぱり俺は天才プログラマーだな!ワッハッハ!
僕が教えてあげただけなのに・・・
【 まとめ 】PowerShellの戻り値をreturn値だけにしたかったら「Out-Null」を使う
- PowerShellの関数の戻り値にはreturnで指定した値と標準出力とAdd関数の処理結果などが複数含まれる
- 標準出力などを戻り値に含めたくない場合は「Out-Null」を付ける
- 戻り値のDataTableは行数によって異なる型で返される
山田君のDataTableの型の判断はちょっとダサいので、関数の外にDataTableの結果確認用の変数を用意してそこに入れるなど、色々と工夫ができそうですね。
最近のコメント