PowerShell 第3回 二次元配列を他の関数に引き渡す

#はじめに
二次元配列を他の関数の引数にしようと思ったところ、かなりつまづきました。
二次元配列を参照しようとしているのに、一次元配列の参照しているようになります。
ArrayList[1,2]のようなときに、ArrayListが二次元配列のつもりで参照しているのに、一次元配列になって、その1番目と2番目の値を参照してしまいます。
くわしい結果は[こちら](https://qiita.com/Mount/items/d10ff1eb41617f4b8368#%E5%A4%B1%E6%95%97%E4%BE%8B%E3%81%AE%E5%AE%9F%E8%A1%8C%E7%B5%90%E6%9E%9C)。
ネットを調べた結果答えはわかったので、自分の備忘のために記載します。

#今回実施する内容
1つ目の関数の戻り値の二次元配列を2つ目の関数の引数にして、2つ目の関数で利用します。

#ソースコード(Git Hub)
[PowerShell_03_DimArrayList](https://github.com/Build-Mount/PowerShell_03_DimArrayList)

#環境
OS: Windows 10 JP (64bit)
PowerShell version: 5.1.19041.1023

#参考
[Powershell：関数の戻り値としての多次元配列 - powershell、多次元配列、戻り値](https://living-sun.com/ja/powershell/679097-powershell-multidimensional-array-as-return-value-of-function-powershell-multidimensional-array-return-value.html)
これがネットで調べた二次元配列を引数にする内容の記事です。

[Microsoft Powershell about_Operators コンマ演算子](https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_operators?view=powershell-7.1#cast-operator--)
コンマ演算子`,`についての説明です。

#用語
なし

#二次元配列を他の関数に引き渡す

ポイントは、引き渡し元の**コンマ演算子`,`**です。ソースコードでは、最後の`,$DimArrayList`の部分です。
たったこれだけなんです。

##ソースコード

```powershell:DimArrayList_success.ps1
function CreateArrayList {
    $DimArrayList = New-Object "Object[,]" 2,2

    $DimArrayList[0,0] = 1
    $DimArrayList[0,1] = "No.1"
    $DimArrayList[1,0] = 2
    $DimArrayList[1,1] = "No.2"

    Write-Host "CreateArrayList"
    Write-Host $DimArrayList[0,0]
    Write-Host $DimArrayList[0,1]
    Write-Host $DimArrayList[1,0]
    Write-Host $DimArrayList[1,1]

    ,$DimArrayList
}

function ReferArrayList {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [Object[,]]$DimArrayList
    )
    Write-Host "ReferArrayList"
    Write-Host $DimArrayList[0,0]
    Write-Host $DimArrayList[0,1]
    Write-Host $DimArrayList[1,0]
    Write-Host $DimArrayList[1,1]

    $newDimArrayList = New-Object "Object[,]" 2,2
    $newDimArrayList = $DimArrayList
    Write-Host "newDimArrayList"
    Write-Host $newDimArrayList[0,0]
    Write-Host $newDimArrayList[0,1]
    Write-Host $newDimArrayList[1,0]
    Write-Host $newDimArrayList[1,1]
}

try {
    $ArrayList = CreateArrayList
    ReferArrayList $ArrayList
} catch {
    Write-Host $Error[0]
}
```

##実行結果
```
CreateArrayList
1
No.1
2
No.2
ReferArrayList
1
No.1
2
No.2
newDimArrayList
1
No.1
2
No.2
```

##CreateArrayList関数の説明

###CreateArrayList関数における二次元配列の生成

`$DimArrayList = New-Object "Object[,]" 2,2`
の記載でObjectの2x2の二次元配列を作ります。動的配列でもよいのですが、今回は宣言で作成します。
Objectなのは意味はありません。私の用途ではObjectにしたかっただけです。

###CreateArrayList関数のコンマ演算子
そのあとは作成した$DimArrayListに値を代入して、本関数内で**コンマ演算子`,`**を使って出力しています。

###コンマ演算子の説明
[Microsoft Powershell about_Operators コンマ演算子](https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_operators?view=powershell-7.1#cast-operator--)の内容を引用します。

>**コンマ演算子 `,`**
>二項演算子として、コンマは配列を作成するか、作成される配列にを追加します。 式モードでは、単項演算子として、コンマは1つのメンバーだけで配列を作成します。 メンバーの前にコンマを配置します。
>
>```Powershell:PowerShell
>$myArray = 1,2,3
>$SingleArray = ,1
>Write-Output (,1)
>```
>`Write-Object`では引数が想定されているため、式をかっこで囲む必要があります。

何を言っているのかよくわかりませんでしたが、この部分が今回の解決策のポイントと理解しました。
>**式モードでは、単項演算子として、コンマは1つのメンバーだけで配列を作成します。 メンバーの前にコンマを配置します。**

**コンマ演算子`,`を付けない場合**、`$DimArrayList`で関数の戻り値を返すと、この時点で二次元配列ではなくなり、1, No.1, 2, No.2の順で、戻っていくようです。
これは**パイプライン処理のための動作**と考えるとそうかと合点が来ました。
Powershellでは、戻り値をreturnで返すような仕様ではなく、処理の中でどんどん値が戻っていく動作です。これはPowershellをやられている方ならばわかる仕様だと思いますが、これを防ぎたい場合はそれなりの書き方をしてきたわけですが、配列を渡す場合もどんどん戻っていくんだなと考えたら、合点が来たということです。
これを**コンマ演算子`,`を付ける**ことで、配列をまとめて１つとして戻すということです。
VBSとかJavaScriptとかJavaとかCとかやってきた私としては、変数なんだから１つを返すでしょうと思っていたのですが、パイプライン処理にまたしてもやられました。

##ReferArrayList関数の説明
特段説明する箇所はないのですが、[CmdletBinding]で、引数の定義を行っています。
ここで引数の型として、`[Object[,]]`として、二次元配列にします。

そのあとのWrite-Hostは値を参照しているだけです。

`$newDimArrayList = New-Object "Object[,]" 2,2`以降については、**コンマ演算子`,`のことがわからずに、どうしたら引き渡せるのか？のトライアルとして、「改めて二次元配列を定義して、引数を入れてみたらどうか？」と考えて実施してみたものの形跡です。ですので、実際には不要な記載です。


##失敗例
うまくいかないと思って記載していたソースコードは以下です。違いは、**コンマ演算子`,`**の有無だけです。

```powershell:DimArrayList_fail.ps1
function CreateArrayList {
    $DimArrayList = New-Object "Object[,]" 2,2

    $DimArrayList[0,0] = 1
    $DimArrayList[0,1] = "No.1"
    $DimArrayList[1,0] = 2
    $DimArrayList[1,1] = "No.2"

    Write-Host "CreateArrayList"
    Write-Host $DimArrayList[0,0]
    Write-Host $DimArrayList[0,1]
    Write-Host $DimArrayList[1,0]
    Write-Host $DimArrayList[1,1]

    $DimArrayList
}

function ReferArrayList {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [Object[,]]$DimArrayList
    )
    Write-Host "ReferArrayList"
    Write-Host $DimArrayList[0,0]
    Write-Host $DimArrayList[0,1]
    Write-Host $DimArrayList[1,0]
    Write-Host $DimArrayList[1,1]

    $newDimArrayList = New-Object "Object[,]" 2,2
    $newDimArrayList = $DimArrayList
    Write-Host "newDimArrayList"
    Write-Host $newDimArrayList[0,0]
    Write-Host $newDimArrayList[0,1]
    Write-Host $newDimArrayList[1,0]
    Write-Host $newDimArrayList[1,1]
}

try {
    $ArrayList = CreateArrayList
    ReferArrayList $ArrayList
} catch {
    Write-Host $Error[0]
}
```

###失敗例の実行結果

```
CreateArrayList
1
No.1
2
No.2
ReferArrayList
1 1
1 No.1
No.1 1
No.1 No.1
newDimArrayList
1 1 
1 No.1
No.1 1
No.1 No.1
```


#おわりに
PowerShellなかなか難しいです。
当たり前と思っている動作が、当たり前に動作しない。
なかなかなじんでこないです。本当に難しい。