PowershellでGenericクラスにインテリセンスが効かないけど効かせる！


# 今日も心の声はダダもれ

~~ああ、サボりたい。~~みなさんこんにちは。
動的型付の言語で、あえて型付をするのは、~~インテリセンスでサボりたいから~~
可読性やメンテナンス性、データ型の保証などの理由からです。

# 動機は単純

C#でいつも使っている`List<T>`って便利ですよね。

~~PowershellにあるPSCustomObject、なんとなく使いたくないです。~~
~~いつも使っている便利なものを持ちこんで、面倒なことはサボりたい。~~
自分の作業の効率化のためにも、どう使うのか見てみましょう。

# とりあえず宣言してみよう

:thinking: 「C#で書くと、Listはこうなりますね。」

```csharp
List<string> SharpList = new List<string>();
SharpList.Add("So Smart!");
```

:thinking: 「う～ん、Powershellだとどう書くんでしょう？」
:thinking: 「ふむふむ、こうやるのか。」

```posh
$DullList = New-ObjectGeneric -className List -typeParameters "string"
```

※問題はここからです。

# 要素を追加してみよう

:smile: 「初期化もできたし、追加してみましょう。」

```powershell
$DullList.Add("feel heavy....")
```

~~（なんだと？ありえない！）~~ ピリオドを打った時点で入力候補が出ないではないですか！！
入力補完機能で~~サボりたいな。ラクしようと思ったのに逆効果ですよ。~~ 素早く入力できるといいですよね。

# 他の方法は？

:smile: 「他の書き方もあるらしいですね！」

```posh
$InertList = New-ObjectGeneric List "string"
```

:smile: 「やってみましょう。」

```powershell
$InertList.Add("feel so tired....")
```

:thinking: 「ああ、これもダメだ。」

# インテリセンスが欲しい

インテリセンスが効く書き方は無いのか探していたら、ありました。

```posh
$HappyList = New-Object System.Collections.Generic.List[string]
```

:smile: 「初期化しているので、さっそく要素の追加ですね。」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/fe3bf9fc-16bf-96d4-9fe4-294d92ad4356.png)

:smile: 「入力候補が出ましたね！」

```powershell
$HappyList.Add("feel light!!★!☆!★!☆!★!☆!★!☆!★!☆!★!☆!★!☆!★!☆!★!☆!")
```

:flushed:「なんだかハッピー過ぎて、お星さまが出てしまいました。お恥ずかしい。」

# ちなみに

:smile: 「こんな書き方でも入力候補が出ました。」

```posh
$HappyList = New-Object System.Collections.Generic.List[string]
```

```posh
$HappyList = [System.Collections.Generic.List[string]]::new()
```

```posh
[System.Collections.Generic.List[string]]$HappyList = [System.Collections.Generic.List[string]]::new()
```

:smile: 「とてもハッピーになれそうです。」

# 辞書はどう？

Listはインテリセンス使って上手くやれそうです。
それでは辞書も同じようにできるといいですね。

```csharp
Dictionary<string,List<string>> SharpDict = new Dictionary<string,List<string>>();
SharpDict.Add("So Smart", new List<string>{"be", "so", "smart", "!"});
```

C#だとこんな感じですね。

## ~~だるいやつ~~入力候補が出ない方法

```posh
$DullDict = New-ObjectGeneric -className Dictionary -typeParameters ("string",$list.GetType().FullName)
```

```posh
$InertDict = New-ObjectGeneric Dictionary ("string", $list.GetType().FullName)
```

## 入力候補が出る方法?

:slight_smile:「同じライブラリにあるクラスなので、当然のようにDictionaryも同じ書き方で大丈夫ですよね！」

```posh
$UnHappyDict = New-Object [System.Collections.Generic.Dictionary[[string,string]]]
```

:slight_smile:「きっとそうですよ！宣言して、次は…」

```posh
$UnHappyDict.Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah!
```

:punch: :angry:「入力候補、出ないじゃないですか！激おこですよ！」

## 今度こそ

これはムズムズしますね。同じライブラリなのにどうして挙動が違うのでしょうか？
そういえば、`List`の時、別の書き方でもインテリセンス効きましたよね？
:smile: 「試してみましょうか。」

```posh
$HappyDict = [System.Collections.Generic.Dictionary[string, string]]::new()
```

:smile: 「さあ、早く出して欲しいです。」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/7900497c-5cce-ab99-77d4-3ed8a4d4a457.png)

:thinking: 「んっ！これは！」

```posh
$HappyDict.Add("It came out!","Oh Yeah!")
```

:smile: 「いっぱい出ましたね。入力候補が！ハッピーになれそうです。」

# どうやら

:smile: 「インテリセンスを効かせて書こうと思うと、これがベストなようですね。」

```posh
$HappyWay = [T[T]]::new()
```

# もっとラクしたい

C#の時って、Listの時には、`List<T>`って書けば使えましたよね。

あれって、あらかじめ`using System.Collections.Generic;`を書いていたからです。

Powershellだと、毎回`[System.Collections.Generic.List[T]]`って長々書かなければいけないのでしょうか？
そんなのは嫌です。「アンパンマンマーチ」の「♪そ～んなのは　い～やだ！」の部分を歌いたいです。

# どうなの出来るの？

ググってみましょう！ぐぐらびりてぃ（Googlability）は最低ですが、何とか見つかりました！~~[公式ドキュメント](https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_using?view=powershell-7.1)に書いてあるのは内緒。~~

:slight_smile:「これを、ps1ファイルの先頭に書いておけば、」

```posh
using namespace System.Collections.Generic
```

:slight_smile:「先ほどのロングスタイル初期化は、なんと！」

```posh
[List[string]]$HappyList = [List[string]]::new()
```

:open_mouth:「こんなに短く出来てしまいました！」

# これで言うことなし

本当に良かったです！これでみんなハッピー！

:smiling_imp:「そうですか？それで満足なんですか？え？」
:smile: 「なんか聞こえるー。幻聴かなー。」
:smiling_imp:　「こういうのはどうするんだい？」

```cs
List<List<int>> DevilList = new List<List<int>>();
```

:smile: 「ああ、見たくないものが見える。目を背けよう」
:smiling_imp:　「さあ、このC#のコードをPowershellで表現してみなさい。」

:smiling_imp:　「もしできなければ…お前のたま」
:scream: 「やめて！お嫁に行けなくなっちゃう！」
:smiling_imp:　「…」

# ネストもできる

:grinning:「めげずにやってみましょう。」

```posh
[List[List[int]]]$AngelList = [List[List[int]]]::new()
```

:thinking: 「インテリセンスは、」

```posh
$AngelList.Add()
```

:grinning:「効きました！」

# あれ？初期化どうやるの？

:imp: 「これ、初期化ってどうやると思う？」
:imp: 「C#だと、こう書くやつ」

```cs
AngelNestList.Add(new List<int> { 1, 2, 3 });
```

:expressionless: 「やべーわかんねー」
:imp: 「こんなのもあるよな」

```cs
List<List<int>> AngelNestList = new List<List<int>>{
    new List<int>{1,2,3},
    new List<int>{4,5,6},
    new List<int>{7,8,9},
};
```

:scream: 「もうやだ！だれか助けてー！」
:angel_tone2: 「こんにちは！普通のGeneric Listはこうやって初期化するのよ」

```posh
[List[string]]$LinearList =[List[string]]@("1","2","3")
Write-Host $LinearList[2]
```

:heart_eyes:「うわ！マジ天使！」
:thinking:「てことは、ネストするときはこんな感じかな？？」

```posh
[List[List[int]]]$GoList =[List[List[int]]]@(
    @(1,2,3),
    @(4,5,6),
    @(7,8,9)
)
Write-Host $GoList[1][1]
```

:laughing:「やった！ちゃんと５が表示された！」
:laughing:「ありがとう天使さん！…あれ？いない…。」

# 辞書は？

:imp: 「どうやら、初期化までインテリセンスを効かせられたようだな」
:smile: 「はい！おかげさまで！スパルタ指導ありがとうございます。」
:imp: 「それじゃあ、`Dictionary<T>`の初期化はどうするかな？こんなやつ」

```cs
List<Dictionary<string, string>> MyFamily = new List<Dictionary<string, string>>()
{
    new Dictionary<string, string>{{Name = "Mickey"},{Kind = "Mouse"}},
    new Dictionary<string, string>{{Name = "Pluto"},{Kind = "Dog"}},
};
```

:tired_face: 「もうつかれた！PSCustomObjectで代用するから許して～～～～～！」

```posh
$MyFamily = [List[PSCustomObject]]@(
    [PSCustomObject]@{ Name = "Mickey"; Kind = "Mouse" },
    [PSCustomObject]@{ Name = "Pluto"; Kind = "Dog" }
)
Write-Host $MyFamily[0].Kind
```

さて、続きはまたの機会に…。

# ごめんなさい

「インテリセンス」の事を、「入力補完」と言ったり、「入力候補」と言ったりして分かりにくいかもです。ご容赦ください。
また、「この書き方もあるよ！」みたいなものがございましたら、コメントにて教えていただけると、はしゃぎます。

**Excelsior!**