PowerShellでGenericなクラスとかメソッドを呼び出す

昨日の記事の中でSystem.Collections.Generic.HashSet<T>というクラスを使いました。 このHashSet<T>というクラスのコンストラクタにはICollection<T>IEnumerable<T>などの配列的な値を渡すことが出来て、集合の初期値とすることが出来ます。

使い方としては以下のような感じ。

PS> [System.Collections.Generic.HashSet[String]]::new(@("alice", "bob", "alice"))

これを実行すると以下のように…エラーになります。残念。

MethodException: Cannot find an overload for "new" and the argument count: "1".

同じような感じで、HashSet<T>.UnionWith(IEnumerable<T>)的なGenericな型が使われているメソッドも呼べません。

残念ながらPowerShellでは一部のコンストラクタやメンバは提供されていないみたい…と思っていたのですが、以下のような情報を頂きました。(ありがとうございます!)

エラー文は「引数が1個のnewってメソッドは無いよ」的な内容に見えるのですが、実際の意味は「引数の型が正しくない」的な意味のようです。

というわけで、引数をString[]にキャストしてあげたら行けました。

PS> [System.Collections.Generic.HashSet[String]]::new([String[]]@("alice", "bob", "alice"))
alice
bob

ちなみに、キャストする前の配列はObject[]だったようです。

PS> (@("alice", "bob", "alice")).GetType().Name
Object[]

PS> ([String[]]@("alice", "bob", "alice")).GetType().Name
String[]

コンストラクタだけでなく、メソッドについても同じことが言えます。

PS> $set = [System.Collections.Generic.HashSet[String]]::new()

PS> # これはダメ
PS> $set.UnionWith(@("alice", "bob"))
MethodException: Cannot find an overload for "UnionWith" and the argument count: "1".

PS> # こっちなら行ける
PS> $set.UnionWith([String[]]@("alice", "bob"))

PS> $set
alice
bob

うまく行きました。 分かれば分かるんですが、うーん…。