【第一回】C#におけるCollectionsの基本のキを理解する

みなさんC#でゲーム作っていますか?
Unityいいですよね。
僕はまだ全く使っていませんが、今作っている『ルカちゃん初めてのテトリス』が完成したら手を出してみたいと思っています(『ルカちゃん初めてのテトリス』はDXライブラリで作っています)。

ゲーム作りが大好きな皆様の中には、「コレクションって聞いたことがあるけど、使い方がよくわからない」とか「それ使ったらどんなメリットがあんの?」と思っている方もいるかもしれませんね(ほら、ゲームは作りたいけどプログラミングはよくわからないって方も多そうじゃないですか。僕とか典型的なソレです)。
そこで今回の記事では、僕なりにコレクションのことをまとめてみようと思います。

ただし!
タイトルには「理解する」と書いていますが、正確には「僕が理解したい」です。
情報として間違っている可能性もありますので、この記事を参考にしてCollectionsを理解しようとしている方はその点ご留意ください。

ここで取り扱うCollectionsについて

ここではSystem.Collections.Generic名前空間に属するCollectionsを取り扱います。
つまりジェネリックでないコレクションは知りません
僕が今まで使用したことのあるCollectionsもジェネリックのものばかりですし、基本的にはジェネリックのCollectionsの使用が推奨されているようですよ(Concurrentというものもあるようですが、ここでは触れません)。

List<T>
Stack<T>
Queue<T>
Dictionary<TKey,TValue>

の順に説明していきたいと思います(現時点ではこれら一つ一つの意味を理解する必要は全くないです)。

Collectionsってそもそもなんやねん

「コレクション」と呼ばれている一群のクラスたちのことですね。
ズバリCollections (C#)を読めば概要が把握できると思いますが、こんな辺境のブログを読んでいるあなたは「長い文章なんて読みたくないよ」と思っている方が大半でしょう。
そこで僕が代わりに一部を抜粋しつつ、説明を付け加えていきます。
手抜きではありません! 適切な引用です!
ちゃちゃっと検索してきて出てきたサイトですけど、アドレス的にこれ公式の情報ってことでいいですよね?
どうせ引用するならなるべく公式のサイトがいいかなと思ってはいるのですが、もし公式サイトじゃなかったらすみません。

注*ちなみにですが、僕の英語力はウンコです。致命的な誤訳があったら「ププッ」と笑っておいてください。
それなのになぜ英語版の資料を引用しているかというと、日本語版がどこにあるのかわからなかった(あと、機械翻訳が多いので日本語翻訳をあまりあてにしていない)ためです。

Collectionsは関連するオブジェクトをグループとして扱う

いきなりですが、Collections (C#)から「コレクションとは何か?」の核となる一文を引用しましょう。
原文:

For many applications, you want to create and manage groups of related objects. There are two ways to group objects: by creating arrays of objects, and by creating collections of objects.

訳:

多くのアプリケーションでは、関連するオブジェクトをグループとして生成したり管理したいはずです。そのための方法が二つあります。すなわち、配列としてオブジェクトを生成する方法と、コレクションとして生成する方法です。

では、配列とコレクションは何が違うのでしょうか?
それもズバリ書いてくれています。

コレクションは要素の最大数を指定する必要がない

またまた引用です。
原文:

Unlike arrays, the group of objects you work with can grow and shrink dynamically as the needs of the application change.

訳:

配列と違い、コレクションはアプリケーションの変化に応じて、オブジェクのグループを動的に拡大したり縮小したりすることができます。

配列はあらかじめ最大値を決めてから使いますよね?
例えばint[] arry = new int[10];なら10個の要素までなら入れられますが、これを11個に拡大することはできません(11個目の要素を入れたらエラーが出ます)。
ところがコレクションの場合、要素を動的に拡大することができるため、要素の最大数を指定する必要もありません
この特徴は、コンパイルの段階では要素数が決められないオブジェクトをグループ化するのに適していると言えるでしょう(たぶんね)。

今まで「うーん、要素がいくつになるかわからないけど、とりあえず100個以上もにはならないっしょ!」と思ってint[] arry = new int[100];などと配列を作成していた箇所をコレクションに置き換えるとスマートになるかもしれませんね。

コレクションの初期化

「ええからコレクションの具体的な使い方教えろや」という方がそろそろ現れてきそうですね。
僕も我慢の限界なのでさっそく構文を紹介します。
ここではとりあえず、最も基本的(と僕は思っている)List<T>型のコレクションの使い方を紹介しましょう。

List<string> colors = new List<string>();
colors.Add(“red”);
colors.Add(“green”);
colors.Add(“blue”);

はい、これでList<T>型のcolorsという変数にList<T>型のインスタンスの参照が代入されたことになります(List<T>型はほとんど配列と同じように使えるコレクションです。詳細はまたのちほど説明します)。
Tの部分がstring型になっているので、追加できる要素はstring型ですね。
その後に続くAddでListに要素を追加していることになります。

コレクションに追加される内容が固定されているなら、インスタンスを生成するときに以下のように指定することも可能です。

List<string> colors = new List<string> { “red”, “green”, “blue” };

暗黙的に型を指定することも、もちろんできます。

var colors = new List<string>();
ちなみにですが、Tの部分には自作したクラスを指定することもできますよ。
これがとっても便利なんですねぇ(ジェネリックの機能であってコレクションとあんまり関係なさそうなので詳細は割愛しますが)。

各要素へアクセスするには

コレクションに追加した全要素を取り出したいだけなら、foreachでコレクションをぶん回す方法が最も簡単でしょう。

foreach (string color in colors)
{
Console.WriteLine(color);
}

あとは配列と同じように、添え字を使ってアクセスすることもできます
colors[0]とすると、redが取り出せますよ。
このことはつまり、forループで各要素にアクセスすることも可能であることを意味します。

注*コレクションによっては添え字(インデックス)でアクセスできないものもあります。ここではList<T>型の話です。

あとはググった感じ、ラムダ式を使って要素を取得する方法もあるみたいです。

僕はラムダ式をうまく使えていないので、このへんは今のところスルー。
要素へアクセスする方法も色々あるんだなあということだけでも覚えておくといいかもしれません。

本日はここまで

とりあえず本日はここまでです。
全何回になるかはわかりませんが、次回からList<T>型のより具体的な使い方を解説していきます。
余裕があればスタックやキューについての概要もチラホラとやりたいですね。

ちなみにですが、具体的と言っても要素の追加や削除レベルです。
プロっぽいテクニックの紹介は一切ありません(だって僕がプログラミング三ヶ月目くらいのど素人ですもん)。

個人的な話になりますが、スタックやキューの説明を通じて、スタックやキュー、ついでにDictionary(これJavaScriptだとMapに相当するみたいですね。言語が違っても似たような機能があって「へー」と思いました)の適切な使い方を学んで行きたいなと思っています。
調べつつ書いているので進行は遅いですが、まあ気長にお付き合いください。

フォローする