C#ユーザーのためのPowerShellチートシート

# 0. はじめに
[Freeradical](https://www.freeradical.jp)の中の人、[yamarah](https://qiita.com/yamarah)です。
C#を普段使っているけど、たまにPowerShellのスクリプトを書くときに都度ググっている人(自己紹介恥ずかしい!!)向けに、とりあえず必要になりそうなことを列挙しました。
これを読んで、あとはググれ!!

# 1. 基礎
## コメント
```C#:C#
// コメント
```
```PowerShell:PS
# コメント
```
## 文字列
"文字列"もしくは'文字列'
## 変数の評価
後述する変数の名前だけや式を書くと、評価結果が出力されます。
```PowerShell:PS
$a = "ABC" # 変数の定義
$a # 変数の内容を出力。Terminalから実行したのならば、ABCが表示される。
1 + 1 # 2を出力。
```
# 2. 変数
大文字、小文字の区別はありません。頭に`$`がつき、1文字目はアルファベット、2文字目以降は数字と一部の記号が使えます。
`\$[a-zA-Z][a-zA-Z0-9_]*`
みたいな感じ。
## 型
`object`, `int`, `double`, `string`, `bool`などのC#の組み込み型が使えます。

## 定義
指定しないと、`object`型になります。
```C#:C#
object a = 1;
object b = "ABC";
```
```PowerShell:PS
$a = 1
$b = "ABC" # もしくは'ABC'
```
変数の型を指定できます。
```C#:C#
int a = 1;
string b = "ABC";
```
```PowerShell:PS
[int]$a = 1
[string]$b = "ABC" # もしくは'ABC'
```
型の種類は、再定義することで何度でも変更可能です。
```PowerShell:PS
[string]$a = "ABC"
$a.GetType().Name #String
[int]$a = 10
$a.GetType().Name #Int32
```
## 変数の消去
C#と違い変数を消去できます。
```PowerShell:PS
$a = 10 # 定義

Remove-Variable a # 変数の消去。以降は使えなくなる。
```
## readonly
特殊な書き方をすれば、`readonly`も可能。
```C#:C#
readonly int a = 10;
```
```PowerShell:PS
SetVariable a 10 -option ReadOnly # 変更不可、削除(Remove-Variable)は可能
SetVariable b 10 -option Constant # 変更も削除も出来ない
```
## 特殊な変数
|C#|PowerShell|
|:-|:-|
|true|$true|
|false|$false|
|null|$null|

また、環境件数を`$env:変数名`で参照できます。

## 未定義の変数
未定義の変数を参照すると、`$null`が返ってきます。
```PowerShell:PS
$Undefined_Variable -eq $null # True
```

# 3. 型変換
PowerShellはスクリプト用途なので、型変換は柔軟(ルーズ)です。
```PowerShell:PS
[int]$a = 2
[int]$b = 5
($a / $a).GetType().Name # Int32
($a / $b).GetType().Name # Dobule
[string]$c = 10 # 勝手に文字列に変換
[int]$d = "10" # 勝手に数値に変換
```
明示的にキャストも出来ます。
```PowerShell:PS
[double]$a = 2.1
$b = [int]$a
$b # 2
$b.GetType().Name # Int32
```

# 4. 演算子
|C#|PowerShell|
|:-|:-|
|==|-eq|
|!=|-ne|
|<|-lt|
|>|-gt|
|<=|-le|
|>=|-ge|
|&&|-and|
|\|\||-or|
|&|-band|
|\||-bor|
|~|-bnot|
|^|-bxor|
|as|-as|
|is|-is|
|is not|-isnot|
|その他|同じ|

`bool`値以外を論理演算にかけると、`0`以外は`$true`になるので注意。
```PowerShell:PS
(1 -and 2) -eq $true # True
(1 -band 2) -eq $true # False
```

# 5. 配列
## 1次元配列
3種類の定義方法がある。
```PowerShell:PS
$a = "a", "b", "c"
$a[0] # a

$b = @("a", "b", "c")
$b[1] # b

$c = @("a"; "b"; "c")
$c[2] # c

$d = ,"a" # 1要素の配列を作る簡易記法
$e = @() # 0要素の配列
```
## 辞書
```PowerShell:PS
$a = @{} # 空の辞書
# 代入すれば、勝手に要素が追加される
$a.A = 65 # ドット(.)で要素名を指定する
$a.B = 66
$a["C"] = 67 # []でインデックス指定でも可

$a.A # 65
$a["B"] # 66

$b = @{A = 65; B = 66; C = 67} # 作成と同時に初期化
$b.C # 67

$b.E -eq $null # True。存在しない要素へのアクセスは$nullが返る。

$b.Count # 3
$b.Remove("C") # 要素の削除
$b.Count # 2
```


# 6. 条件分岐
## if/elseif/else
```C#:C#
if (a == 1)
{
    // 処理1
}
else if (a == 2)
{
    // 処理2
}
else
{
    // 処理3
}
```
```PowerShell:PS
if ($a -eq 1)
{
    # 処理1
}
elseif ($a -eq 2)
{
    # 処理2
}
else
{
    # 処理3
}
```
また、各ブロックに値を書くことで三項演算子やswitch式のように使えます。
```PowerShell:PS
$a = 10
$b = if ($a -gt 0)
{
    "Positive"
}
elseif ($a -lt 0)
{
    "Negative"
}
else
{
    "Zero"
}
$b # Positive
```
## その他
`switch`とかあるけど、ここでは説明しない。必要になったらググれ!

# 7. ループ
## for, break, continue
```C#:C#
for (int i = 0; i < 10; i++)
{
    if (i % 2 == 0)
    {
        continue;
    }
    if (i > 5)
    {
        break;
    }
    Console.WriteLine(i);
}
```
```PowerShell:PS
for ([int]$i = 0; $i -lt 10; $i++)
{
    if ($i % 2 -eq 0)
    {
        continue
    }
    if ($i -gt 5)
    {
        break
    }
    echo $i
}
$i # 生きていて、7が返る
```

## foreach
```C#:C#
var array = { 1, 2, 3, 4, 5 };
foreach (var item in array)
{
    Console.WriteLine(item);
}
```
```PowerShell:PS
$array = 1, 2, 3, 4, 5
foreach ($item in $array)
{
    echo $item
}
```
## その他
`do`とか`while`とかあるけど、ここでは説明しない。必要になったらググれ!

# 8. 関数
## 定義
戻り値の型を限定できないようです。
```PowerShell:PS
function IsEven([int] $value)
{
    return $value % 2 -eq 0
}
```
## 呼び出し
関数名の後にカッコを付けずに引数をスペース区切りで列挙します。
```PowerShell:PS
function Add([int]$a, [int]$b)
{
    return $a + $b
}

$a = Add 1 100
$b = Add 2 100
$a # 101
$b # 102
```
関数の戻り値を、関数の引数にする場合には、注意が必要です。
```PowerShell:PS
function IsEven([int] $value)
{
    return $value % 2 -eq 0
}

function Add([int]$a, [int]$b)
{
    return $a + $b
}

$a = IsEven (Add 2 6)
$a # True
```
最後から2行目で、`IsEven`の後にカッコがありますが、これはC#での関数引数を示すものではないので注意してください。
カッコをつけないと、`Add`, `2`, `6`の3つの引数が`IsEven`に渡されます。
カッコは、その中を評価して結果を得るためのものです。

ややこしいことに、PowerShellのfunctionではなく.NETの関数を呼ぶ場合は、C#のようにカッコが必要です。
```PowerShell:PS
"ABCDEF".SubString(1, 2) # BC
```

# 9. 外部クラス、オブジェクト
## オブジェクトの作成
型名のあとに、コンストラクタへの引数をコンマ区切りで渡す。
```PowerShell:PS
$a = New-Object DateTime 2025, 1, 26
```
## staticな変数へのアクセス
```PowerShell:PS
[Math]::PI # 3.14159265358979
```
## using
```C#:C#
using System.Text;

var a = new StringBuilder("Initial Text");
Console.WriteLine(a.ToString());
```
```PowerShell:PS
using namespace System.Text

$a = New-Object StringBuilder "Initial Text"
$a.ToString()
```

# 10. その他
外部DLLの読み込み、正規表現の使用、ファイル操作の便利な機能、COMオブジェクトの作成などできるけど、ここでは説明しない。必要になったらググれ!