配列の要素数につきまして

お世話になります。Uipathか.Netかどちらの仕様かわかりませんが
以下のようなことをした際に、配列の要素数が2→10に増えてますが
そういうものなのでしょうか。
※個人的には最初に要素数2で宣言していた場合は増えない認識でした。

なぜこのような動きになるのか不明でなので
ご教示頂ければと思います。

■実施した動作
①文字列配列「ArrayFile」を作成

変数名;ArrayFile
型;String
初期値:new string(1){“A”,“A”}

②ArrayFile.Lengthの結果は2

③AssignでArrayFileにsystem.IO.Directory.GetFiles(“C:\temp”)を代入する
※C:\tempには10個のExcelファイルしかない

④ArrayFile.Lengthの結果は10

多分、
System.IO.Directory.GetFiles
が綺麗な配列を返却したため?

配列数2と限定しているのは、仕様なのでしょうか?
なら、GetFilesからの返却配列で、必要数を捕らえるのは出来ますね。

ただ、GetFilesからの返却配列の順番は不定のようですので、Sortなんなりの処理は必要ですね。

ありがとうございます。
System.IO.Directory.GetFilesに限らず
配列で返すようなものを受け取った際には
宣言した要素数を無視するってことですかね?

配列数2としてSystem.IO.Directory.GetFilesをしたいのではなく
今回たまたまこういうことを発見したので
宣言した要素数より増えることがあるのかが知りたかった次第です。

1 Like

GetFilesちゃんの言い分としては、

ちゃんとフォルダ中のファイル一覧を取ったよ、
全部返却するから、あとは好きにしてね

って事でしょうね。

そうなんですね。
GetFiles「一覧10個あるよー全部渡すね」
配列(UiPath)「ええ~。2個しかもてないから受け取れないよ~」
でエラーにならずに
配列(UiPath)「よし10個分格納できるようにしたぜ。確かに受け取ったぜ」
ってなるんですね、

説明が難しいのですが、GetFilesが返すものが「配列全体」そのものであるので、それを変数に代入しているために発生する挙動だと思います。

あー
イメージとしては配列をまるっと受け取る
なので再度宣言しなおしている感じですかね。

ArrayFile = new string(10){“C:\temp\1.xlsx”,“C:\temp\2.xlsx”~~~}

のような。

厳密には違っていまして、UiPathというよりも .NET(というより数多あるプログラミング言語のいくつか)の仕様として配列を変数に格納するときは、配列の中身が変数に入るのではなく、配列がメモリ上どこにあるかという位置が変数に入ります。

上記のタイミングで、それまでに作っていた配列の「位置」の情報が、新しくGetFilesで生成された配列の「位置」に置き換わった、というイメージです。

1 Like

んー
GetFilesで生成された配列のアドレスを
ArrayFileは見に行っているってことですよね。

★GetFilesする前
ArrayFileはメモリ上の00000000を参照(初期に確保された領域)
※アドレスは適当

★GetFilesした後
ArrayFileはメモリ上の00000010を参照(GetFilesに確保された領域)
※アドレスは適当

理解が乏しいですが、たぶんこのような感じかなと。。

なのでGetFiles前に確保していた領域は解放されているかもしくは残ったままか

1 Like

そうですね。たぶんガベージコレクトで消えるはずです。

ありがとうございます。
とりあえず解放の部分を調べようと思いましたが
UiPath(.Net)でアドレス取得のやり方が不明だったのであきらめます。

2 Likes

System.IO.GetFiles()の、ソースコードを追っていくと、List<String>で結果を作成したあと、ToArray()していました。

更に、その中を辿ると、

T[] array = new T[_size];
Array.Copy(_items, 0, array, 0, _size);
return array;

と、新規に領域を確保しています。
System.Arrayはマネージド型なので、破棄されている筈です。

1 Like

厳密な調査では、ないのですが、ArrayCreateTest.xaml (6。1 キロバイト)
Garbage Collectionの世代を見ることで、新しく配置されていることは、確認できますね。

前の配列が、きちんと破棄されることを確認するには、巨大な配列を用意して、GC.Collectした後、ヒープが解放されるか、空きメモリをチェックするぐらいしか、方法が思いつきません。