ここでは非ジェネリックなコレクション型System.Collections.Queueクラスについて解説します。 Queueクラスを使用するよりも、Queueに相当するジェネリックなコレクション型System.Collections.Generic.Queue<T>クラスを使用することを強く推奨します。

Queue

System.Collections.Queueクラスは、先入れ先出し(FIFO: First-In, First-Out)のデータ構造を持つキューを提供するコレクションクラスです。 Queueクラスでは、ArrayListクラスやHashtableクラスとは異なり、コレクションにどのようなオブジェクトが格納されているかということより、どのような順番で格納されたかと言うことの方が重要視されます。

基本的な操作

キュー
Alice Alice Alice Bob Bob Bob Charlie Charlie Bob enqueue enqueue dequeue Charlie Alice

.NET FrameworkにおけるQueueクラスの概要を見ていきます。 Queueに要素を追加するエンキューの操作はEnqueueメソッド、Queueから要素を取り出すデキューの操作はDequeueメソッドで行います。 Queueから要素をデキューすると、取り出した要素はQueueから削除されます。 待ち行列の最後尾に一人並べる作業がエンキュー、待ち行列の先頭から一人引き抜く作業がデキューに相当するとイメージするとよいと思います。

また、Peekメソッドを使うと、Queueの内容はそのままで(削除されずに)先頭にある要素を取得できます。 Queueの内容が空の場合に、DequeueメソッドやPeekメソッドを呼び出すとInvalidOperationExceptionがスローされます。 Queueの内容を空にするには、Clearメソッドを使います。 Queueに指定した内容の要素が含まれているか調べるには、Containsメソッドを使います。

Queueに現在いくつの要素が含まれているかを知るにはCountプロパティを参照します。 ArrayListなどと同様、Queueには任意の数の要素をエンキューできます。 Queue内部の容量はエンキューの際に自動的に拡充されます。 デキューの際に要素数が減っても、Queue内部で確保されている容量は減ることはありません。

using System;
using System.Collections;

class Sample {
  static void Main()
  {
    Queue q = new Queue();

    // Queueに要素をEnqueue
    q.Enqueue("Alice");
    q.Enqueue("Bob");
    q.Enqueue("Charlie");
    q.Enqueue("Dave");
    q.Enqueue("Eve");

    Console.WriteLine("Count: {0}", q.Count);

    // Queueの先頭にある要素をPeek
    Console.WriteLine("Peek: {0}", q.Peek());

    Console.WriteLine("Count: {0}", q.Count);

    // Queueの先頭にある要素をDequeue
    Console.WriteLine("Dequeue: {0}", q.Dequeue());
    Console.WriteLine("Dequeue: {0}", q.Dequeue());

    Console.WriteLine("Count: {0}", q.Count);

    // Queueに"Alice", "Eve"が含まれるか調べる
    Console.WriteLine(q.Contains("Alice"));
    Console.WriteLine(q.Contains("Eve"));

    // Queueに"Fran", "Gordon"をEnqueue
    q.Enqueue("Fran");
    q.Enqueue("Gordon");

    Console.WriteLine();

    // Queueが空になるまで内容をDequeue
    while (0 < q.Count) {
      Console.WriteLine(q.Dequeue());
    }
  }
}
Imports System
Imports System.Collections

Class Sample
  Shared Sub Main()
    Dim q As New Queue()

    ' Queueに要素をEnqueue
    q.Enqueue("Alice")
    q.Enqueue("Bob")
    q.Enqueue("Charlie")
    q.Enqueue("Dave")
    q.Enqueue("Eve")

    Console.WriteLine("Count: {0}", q.Count)

    ' Queueの先頭にある要素をPeek
    Console.WriteLine("Peek: {0}", q.Peek())

    Console.WriteLine("Count: {0}", q.Count)

    ' Queueの先頭にある要素をDequeue
    Console.WriteLine("Dequeue: {0}", q.Dequeue())
    Console.WriteLine("Dequeue: {0}", q.Dequeue())

    Console.WriteLine("Count: {0}", q.Count)

    ' Queueに"Alice", "Eve"が含まれるか調べる
    Console.WriteLine(q.Contains("Alice"))
    Console.WriteLine(q.Contains("Eve"))

    ' Queueに"Fran", "Gordon"をEnqueue
    q.Enqueue("Fran")
    q.Enqueue("Gordon")

    Console.WriteLine()

    ' Queueが空になるまで内容をDequeue
    While 0 < q.Count
      Console.WriteLine(q.Dequeue())
    End While
  End Sub
End Class
実行結果
Count: 5
Peek: Alice
Count: 5
Dequeue: Alice
Dequeue: Bob
Count: 3
False
True

Charlie
Dave
Eve
Fran
Gordon

一番最初にQueueに入れた要素は一番始めに取り出されるという特性上、要素を入れた順番と同じ順番で表示されている点に注目してください。

列挙操作

Queueでも、foreach文による列挙ができるようになっていますが、インデクサはサポートされないのでfor文による列挙は出来ません。 foreach文による列挙を行う場合は、Dequeueしたときと同じ順で列挙されますが、当然要素の削除は行われません。

using System;
using System.Collections;

class Sample {
  static void Main()
  {
    Queue q = new Queue();

    q.Enqueue("Alice");
    q.Enqueue("Bob");
    q.Enqueue("Charlie");
    q.Enqueue("Dave");
    q.Enqueue("Eve");

    foreach (object e in q) {
      Console.WriteLine(e);
    }

    Console.WriteLine("Count: {0}", q.Count);
    Console.WriteLine();

    while (0 < q.Count) {
      Console.WriteLine(q.Dequeue());
    }

    Console.WriteLine("Count: {0}", q.Count);
  }
}
Imports System
Imports System.Collections

Class Sample
  Shared Sub Main()
    Dim q As New Queue()

    q.Enqueue("Alice")
    q.Enqueue("Bob")
    q.Enqueue("Charlie")
    q.Enqueue("Dave")
    q.Enqueue("Eve")


    For Each e As Object In q
      Console.WriteLine(e)
    Next

    Console.WriteLine("Count: {0}", q.Count)
    Console.WriteLine()

    While 0 < q.Count
      Console.WriteLine(q.Dequeue())
    End While

    Console.WriteLine("Count: {0}", q.Count)

  End Sub
End Class
実行結果
Alice
Bob
Charlie
Dave
Eve
Count: 5

Alice
Bob
Charlie
Dave
Eve
Count: 0

配列からの変換

配列からQueueに変換するには、コンストラクタが使えます。 コンストラクタに配列を指定した場合、Queueの内容は配列の要素を先頭から一つずつEnqueueした場合と同じ内容になります。

using System;
using System.Collections;

class Sample {
  static void Main()
  {
    string[] arr = new string[] {"Alice", "Bob", "Charlie", "Dave", "Eve"};
    Queue q = new Queue(arr); // 配列からQueueを作成

    while (0 < q.Count) {
      Console.WriteLine(q.Dequeue());
    }
  }
}
Imports System
Imports System.Collections

Class Sample
  Shared Sub Main()
    Dim arr() As String = New String() {"Alice", "Bob", "Charlie", "Dave", "Eve"}
    Dim q As New Queue(arr) ' 配列からQueueを作成

    While 0 < q.Count
      Console.WriteLine(q.Dequeue())
    End While
  End Sub
End Class
実行結果
Alice
Bob
Charlie
Dave
Eve

配列への変換・コピー

Queueから配列へ変換する場合にはToArrayメソッドCopyToメソッドが使えますが、ArrayListから配列の変換の場合とは異なり、object型の配列への変換しかサポートされていません。 変換・コピーした後の配列の内容は、Queueの内容を一つずつDequeueした場合と同じ内容になります。 また、変換・コピーの前後でQueueの内容は変化しません。

using System;
using System.Collections;

class Sample {
  static void Main()
  {
    Queue q = new Queue();

    q.Enqueue("Alice");
    q.Enqueue("Bob");
    q.Enqueue("Charlie");
    q.Enqueue("Dave");
    q.Enqueue("Eve");

    // 配列に変換
    object[] arr1 = q.ToArray();

    for (int i = 0; i < arr1.Length; i++) {
      Console.WriteLine("arr1[{0}]: {1}", i, arr1[i]);
    }

    Console.WriteLine("Count: {0}", q.Count);

    // 配列にコピー
    object[] arr2 = new object[q.Count];

    q.CopyTo(arr2, 0);

    for (int i = 0; i < arr2.Length; i++) {
      Console.WriteLine("arr2[{0}]: {1}", i, arr2[i]);
    }

    Console.WriteLine("Count: {0}", q.Count);
  }
}
Imports System
Imports System.Collections

Class Sample
  Shared Sub Main()
    Dim q As New Queue()

    q.Enqueue("Alice")
    q.Enqueue("Bob")
    q.Enqueue("Charlie")
    q.Enqueue("Dave")
    q.Enqueue("Eve")

    ' 配列に変換
    Dim arr1() As Object = q.ToArray()

    For i As Integer = 0 To arr1.Length - 1
      Console.WriteLine("arr1[{0}]: {1}", i, arr1(i))
    Next

    Console.WriteLine("Count: {0}", q.Count)

    ' 配列にコピー
    Dim arr2(q.Count) As Object

    q.CopyTo(arr2, 0)

    For i As Integer = 0 To arr2.Length - 1
      Console.WriteLine("arr2[{0}]: {1}", i, arr2(i))
    Next

    Console.WriteLine("Count: {0}", q.Count)
  End Sub
End Class
実行結果
arr1[0]: Alice
arr1[1]: Bob
arr1[2]: Charlie
arr1[3]: Dave
arr1[4]: Eve
Count: 5
arr2[0]: Alice
arr2[1]: Bob
arr2[2]: Charlie
arr2[3]: Dave
arr2[4]: Eve
Count: 5