PowerShell の function について、param 内で [int] を指定した場合、該当する引数に小数点以下があれば銀行型丸め(Banker's Rounding:四捨五入、.5の時は最も近い偶数にまるめる)が行われます。
function Normal {
param(
[int]$Var
)
$Type = $Var.GetType().FullName
return "Value: $Var ($Type)"
}
PS C:> Normal 0.5
Value: 0 (System.Int32)
PS C:> Normal 1.5
Value: 2 (System.Int32)
PS C:> Normal -2.5
Value: -2 (System.Int32)
PS C:> Normal -3.5
Value: -4 (System.Int32)
これを、引数に小数点以下があった場合、丸めるのではなくエラーにしてしまおう!というのが今回の趣旨です。
↓こんな感じ
class strict: Management.Automation.ArgumentTransformationAttribute {
$type; strict($type) { $this.type = $type }
[object] Transform([Management.Automation.EngineIntrinsics]$EngineIntrinsics, $input) {
try {
if ("$($this.type)" -eq "") { throw ":引数に指定した型が未知です。" }
if ($this.type -isnot [type]) { throw ":引数 " + "$($this.type)" + " は System.Type ではありません。" }
if ($input -isnot $this.type) { throw ":型 " + $this.type.FullName + " との不一致" }
} catch {
throw $_.Exception.Message
}
return $input
}
}
function Strict {
param(
[strict([int])]$Var
)
$Type = $Var.GetType().FullName
return "Value: $Var ($Type)"
}
PS C:> Strict 1.5
Strict : パラメーター 'Var' の引数変換を処理できません。:型 System.Int32 との不一致
発生場所 行:1 文字:8
+ Strict 1.5
+ ~~~
PS C:> Strict 2.0
Strict : パラメーター 'Var' の引数変換を処理できません。:型 System.Int32 との不一致
発生場所 行:1 文字:8
+ Strict 2.0
+ ~~~
PS C:> Strict 2
Value: 2 (System.Int32)
PS C:> Strict (-3)
Value: -3 (System.Int32)
簡単な解説
Class が ArgumentTransformationAttribute を継承している場合、[Class(Args)]$Opt という属性構文が param ブロック内で使用されると Transform() をフックします。またそのとき Args はコンストラクタの引数、$Opt は Transform の引数になります。引数に要求する型をコンストラクタを使って取得し、Transform メソッド内で引数の型を検証しています。
そのほか
パラメータ検証属性 を作ってみても同じことができそうです。
また ValidateScript を使う方法もあります。
function Validate {
param(
[ValidateScript({$_ -is [int]})]$Var
)
}
参考にしたサイト
Powershell: Creating parameter validators and transforms
Custom Parameter Coercion with the ArgumentTransformationAttribute