Frameworkが提供するStack<T>クラスの基本的な使い方と注意点を説明する。List<T>クラスを使ったスタックの独自実装コードも紹介する。TIPS」スタック(積み重ね)とは、入れたものが入れたときとは逆の順で出てくるコレクションのことだ。out")のコレクションともいう。2.0以降ではStack<T>コレクション(System.Collections.Generic名前空間)を利用するとよい。本稿では、Stack<T>コレクションの基本的な使い方とスタックのサイズを制限する方法を解説する。Stack<T>コレクションの基本的な使い方Stack<T>コレクションの基本的な使い方まとめ特定のトピックをすぐに知りたいという方は以下のリンクを活用してほしい。2015以降が必要である。サンプルコードはコンソールアプリの一部であり、コードの冒頭に以下の宣言が必要となる。System.Console本稿のサンプルコードに必要な宣言(上:C#、下:VB)Stackの基本的な使い方とは?スタックに対する基本的な操作は、「スタックにデータをぎゅっと押し込む」(push)/「スタックからデータをぽんと取り出す」(pop)/「一番上にあるデータを見る」(peek)の3つだ。Stack<T>コレクションは、それらを次の3つのメソッドとして実装している。Pushメソッド:スタックの上端にデータを追加するPopメソッド:スタックの上端からデータを取り出すPeekメソッド:スタックの上端のデータを読み取る(取り出さない)Pushメソッドでデータをスタックの上端に追加するとき、スタックに空きがなければ自動的にスタックのサイズが拡張される。この他に、Stack<T>コレクションにはスタックに入っているデータの数を返すCountプロパティもある。スタックにデータが入っていないときにPop/Peekメソッドを呼び出すと例外が出るので、呼び出す前にCountプロパティをチェックすべきである。Stack<T>コレクションはIEnumerable<T>インタフェース(System.Collections.Generic名前空間)を実装しているので、LINQ拡張メソッドも利用できる。Stack<T>コレクションはスレッドセーフではない。非同期/並列処理でStack<T>コレクションにアクセスするにはスレッド間の排他処理が必要になる。その手法はキューと同様なので、次のTIPSを参照していただきたい。4.0以降、C#/VB]Stack<T>コレクションの基本的な使い方の例を示す(次のコード)。SubStack<T>コレクションの基本的な使い方の例(上:C#、下:VB)Pushメソッドを使って文字列の"A"、"B"、"C"を順にスタックに投入している。その後、Popメソッドを使ってスタックから1つずつ取り出すと、投入したときとは逆の順で"C"、"B"、"A"と出てくる。Peekメソッドは、得られる値はPopメソッドと同じだが、Popメソッドとは違ってそのデータはスタックに残ったままになる(スタックに入っている個数が変化しない)。Stack<T>コレクションのIEnumerable<T>インタフェースとLINQ拡張メソッドを利用する例を示す(次のコード)。Stack<T>コレクションには最後の要素を読み取るメソッドは用意されていないが、LINQのLast拡張メソッドを使えばよいのである。aStack<T>コレクションのIEnumerable<T>インタフェースを利用する例(上:C#、下:VB)IEnumerable<T>インタフェースを実装しているので、StringクラスのJoinメソッドの引数として使える。Each(VB)ステートメントを使ってスタックの内容を順に読み取ることも可能だ。LINQ拡張メソッドが使えるので、スタックの末尾を読み取ったり、スタックの全要素に同じ処理を加えたりなど、LINQ拡張の多様な機能も利用できる。コレクションを与えて初期化したときの格納順は?Stack<T>クラスをインスタンス化するときに、他のコレクションを与えることもできる。そのときの格納順は、与えたコレクションとは逆順になるので注意してほしい。元のコレクションの先頭にあるデータから順にPushしていったのと同じ結果になるのだ(次のコード)。1既存のコレクションを与えてStackを初期化する例(上:C#、下:VB)整数の配列(内容は1、2、3)をStack<T>クラスのコンストラクタに与えた。スタックの内容を表示させると逆順の3、2、1になっている。これは、与えたコレクションの先頭の1から順にスタックへPushした形になっている。スタックの下端を削除してサイズを制限するには?スタックは、キューと同様にしてデータの受け渡しに使う他に、履歴を保持しておいてundo(元に戻す)/redo(やり直し)を実現するためにもよく使われる。ユーザーの操作履歴や画面の遷移履歴などだ。履歴の場合は(データの受け渡しとは異なり)、スタックのサイズが増え続ける。一定のサイズを超えたら古いデータを削除する処理が必要になってくるのだ。スタックから要素を削除する方法はPopメソッド(上端を1つ削除する)しか用意されていない。そこで、下端を削除するには、いったん別のコレクションにコピーし、削除してから新しいスタックを作ればよい(次のコード)。前述したようにコレクションを渡してスタックを初期化するときは逆順になるので、その点は注意する必要がある。BStackの下端の要素を1つ削除する例(上:C#、下:VB)1つ追加するごとに1つ削除していたのではスタックの再作成が毎回発生してしまうので、実際には例えば最大容量の半分をまとめて削除するなどを行う。その実装方法もいろいろと考えられるが、ここではLINQ拡張のReverseとSkipを使って1つ削除したコレクションを作り、それをStack<T>クラスのコンストラクタに渡している。それによってどのようにデータが変化するかを、コメントに記しておいた。array」と明記されている)。配列なのでコンパクトで高速にアクセスできるが、途中の要素の削除はできないのである。そこで、履歴に使うのであれば、発想を切り替えて自前のコレクションを作ってしまってもよい。そのようなMyStack<T>クラスの例を、参考までにC#だけであるが掲載しておく(次のコード)。スタックの内容:(0個)......省略......下端が自動的に削除されるスタックの実装例(C#)ここではLinkedList<T>クラス(System.Collections.Generic名前空間)を使って実装してみた。Pushされたときは、AddFirstメソッドで上端に挿入し、それで最大サイズを超えた場合にはRemoveLastメソッドで下端の要素を削除している。まとめスタック(積み重ね)は、処理待ちのデータを一時的に蓄えておくのに適したコレクションだ。履歴の保持にも使えるが、最大サイズを制限する(下端のデータを削除する)にはちょっとした工夫が必要になる。メールマガジンをご購読ください。申し込みページへITmediaはアイティメディア株式会社の登録商標です。