どうも、動的型付なPowerShellです。 といっても型好きなPowerShellerです。
ということで、だれもがイラッとする型安全ではない(type-unsafe) Hashtableを型安全(type-safe)にできないかというのが今回の記事です。
Hashtableとは
ようは連想配列ですね。
MSDN - Hashtable クラス.aspx)
基本的な使い方はHey, Scripting Guy! 様にお出まし願います。
Hey, Scripting Guy! Blog // Easily Create a PowerShell Hash Table
さて、今回の狙いはこのHashtableのName.Valueを型制約できないかという事を試します。
通常のHashtable
例えば以下のHashtable $employeeを考えます。
- KeysがNO、Valueが123456
- KeysがName、ValueがAlice
これを作るには、@{K=V}や@{}の.Key=ValueとHashtableのプロパティ指定で作成するのが一般的でしょう。
# Week Typed Hash Table PS> $emploee = @{} PS> $emploee.NO = 123456 PS> $emploee.Name = "Alice" PS> $emploee Name : Name Value : Alice Name : NO Value : 123456
PSCustomObjectにキャストすれば他のオブジェクト同様に使いやすくなりますね
Name NO ---- -- Alice 123456
通常のHashtableは型安全ではない(type-unsafe)
先ほど、"Alise"としたValueの型を見てみると、
$emploee.Name.GetType().FullName
string型になっています。
System.String
では、作った$employee{}.NameキーのValueに数値を入れてみましょう。
$emploee.Name = 456
動的型付けにより、型変換エラーなく入ってます。出力してみましょう。
PS> $emploee Key : NO Value : 123456 PS> [PSCustomObject]$emploee | Format-Table -AutoSize NO Name -- ---- 123456 456
NameキーのValueの型を調べるとint型になっていますね
PS> $emploee.Name.GetType().FullName
System.Int32
このようにPowerShellの@{K=V}で作成したHashtableは、型制限がなく動的に型変換されます。
Hashtableを型制約して型安全(type-safe)にする
Hashtableは、System.Collections.Hashtableを生成しているわけです。 つまり、このコードでも@{}と同等のHashtableが生成されます。
$hash = @{} $hashDotNet = New-Object 'System.Collections.Hashtable' #hashと一緒
ならば、作成時に、K,Vそれぞれの型を制約すればいいわけです。そこで、GenericなDictionaryを使います。 イメージ的にはこうです。
System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
Dictionaryを作ってK,Vに値を入れてみましょう。
$emploeeTyped = New-Object 'System.Collections.Generic.Dictionary[string, int]' $emploeeTyped.NO = 123456
エラーなく上手く入ったようですので確認します。
PS> $emploeeTyped Key : NO Value : 123456
では、Vに文字列を入れてみます。int型にはstring型を入れられませんと、きっちりはじいてくれました。
PS> $emploeeTyped.Name = "Margaret" 値 "Margaret" を型 "System.Int32" に変換できません。エラー: "入力文字列の形式が正しくありません。" 発生場所 D:\Document\Program\Powershell\TypedHashtable\TypedHashtable.ps1:17 文字:1 + $emploeeTyped.Name = "Margaret" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument: (:) []、RuntimeException + FullyQualifiedErrorId : InvalidCastFromStringToInteger
当然、NoのK,Vしか入っていません。
PS> $emploeeTyped Key : NO Value : 123456
例えDisctionaryにしても,[PSCustomObject]へのキャストはできるので安心です。
PS> [PSCustomObject]$emploeeTyped Key Value --- ----- NO 123456
まとめ
これで、Hashtableが型安全(type-safe)に生成できます。
PSCustomObjectという便利なオブジェクト生成手段に利用するため、HashtableというよりDictionaryにして使い勝手を管理できると嬉しいですね。
ただ、PowerShellは動的型付なのでHashTableでも型エラーがでないので気にされにくいのでしょうか…今更ネタかなぁ…。
補足
LINQ星人の指摘で、Hashtableのクラス間違えていたので修正しました。