【C#】Queueの基本:FIFO(先入れ先出し)コレクションの使い方

目次

Queue<T>とは何か? FIFO(先入れ先出し)

C#のSystem.Collections.Generic名前空間には、List<T>(動的配列)やStack<T>(スタック)と並び、Queue<T>(キュー)という特定の操作に特化したコレクションが用意されています。

Queue<T>(キュー)は、「FIFO (First-In, First-Out)=先入れ先出し」というデータ構造を実装したものです。

これは、現実世界の「窓口の行列」や「レジの順番待ち」に例えられます。

  • 新しい人(データ)は、常に行列の**一番後ろ(End)**に並びます。
  • 処理(データを取り出す)は、常に**一番前(Front)**にいる人から行われます。

このFIFOの特性は、タスクの待機列(例: 印刷ジョブ、リクエスト処理)など、「受け付けた順番通りに」処理を実行したいロジックを実装するのに最適です。


Queue<T>の基本的な操作

Queue<T>の操作は、List<T>Addとは異なる、専用のメソッド名(Enqueue, Dequeue)を使用します。

  • Enqueue(T item): キューの一番後ろに新しい要素を追加(エンキュー)します。
  • Dequeue(): キューの一番前から要素を取り出し、かつ削除(デキュー)します。
  • Peek(): キューの一番前の要素を削除せずに参照(ピーク=覗き見)するだけです。
  • Count: キューに現在含まれている要素の数を取得します。

コード例1:基本的な Enqueue, Dequeue, Peek

プリンターの待機ジョブをQueue<string>で管理する例です。

using System;
using System.Collections.Generic; // Queue<T> を使うために必要

public class QueueBasicExample
{
    public static void Main()
    {
        // 1. string 型の Queue を初期化
        var printQueue = new Queue<string>();

        // 2. Enqueue: データを待ち行列(キュー)の後ろに追加
        printQueue.Enqueue("DocumentA.pdf");
        printQueue.Enqueue("ImageB.png");
        printQueue.Enqueue("SpreadsheetC.xlsx");

        Console.WriteLine($"--- 印刷ジョブが追加されました ---");
        Console.WriteLine($"現在の待機ジョブ数: {printQueue.Count}"); // 3

        // 3. Peek: 一番前(最初に追加した)の要素を「削除せず」に参照
        string nextJob = printQueue.Peek();
        Console.WriteLine($"\n次に印刷するジョブ: {nextJob}");
        Console.WriteLine($"Peek後のジョブ数: {printQueue.Count}"); // 3 (減っていない)

        // 4. Dequeue: 一番前(最初に追加した)の要素を「削除して」取り出す
        string currentJob = printQueue.Dequeue();
        Console.WriteLine($"\n印刷を実行: {currentJob}");
        Console.WriteLine($"Dequeue後のジョブ数: {printQueue.Count}"); // 2 (1つ減った)

        // 5. 再度 Peek (先頭が変わっている)
        Console.WriteLine($"\n次に印刷するジョブ: {printQueue.Peek()}"); // "ImageB.png"
    }
}

出力結果:

--- 印刷ジョブが追加されました ---
現在の待機ジョブ数: 3

次に印刷するジョブ: DocumentA.pdf
Peek後のジョブ数: 3

印刷を実行: DocumentA.pdf
Dequeue後のジョブ数: 2

次に印刷するジョブ: ImageB.png

whileループによるキューの処理

キューに溜まった全要素を、while (queue.Count > 0)ループとDequeueメソッドを使って、FIFO(先入れ先出し)の順序ですべて処理するのは一般的なパターンです。

using System;
using System.Collections.Generic;

public class QueueWhileLoopExample
{
    public static void Main()
    {
        var taskQueue = new Queue<int>();
        taskQueue.Enqueue(101); // 1番目に追加
        taskQueue.Enqueue(102); // 2番目に追加
        taskQueue.Enqueue(103); // 3番目に追加

        Console.WriteLine("--- キューの全タスクを処理 (FIFO) ---");
        
        // キューの要素数が 0 より大きい間、ループ
        while (taskQueue.Count > 0)
        {
            // 一番前 (最初に追加した 101) から順番に取り出される
            int item = taskQueue.Dequeue();
            Console.WriteLine($"Task ID: {item} を処理しました。");
        }

        Console.WriteLine($"処理後の残存タスク数: {taskQueue.Count}"); // 0
    }
}

出力結果:

--- キューの全タスクを処理 (FIFO) ---
Task ID: 101 を処理しました。
Task ID: 102 を処理しました。
Task ID: 103 を処理しました。
処理後の残存タスク数: 0

注意点と安全な操作:TryDequeue / TryPeek

Queue<T>が**空(Count0)**の状態で、Dequeue()またはPeek()メソッドを呼び出すと、InvalidOperationExceptionという実行時エラーが発生してプログラムが停止します。

これを避けるため、while (queue.Count > 0)のようにCountをチェックする方法の他に、bool値を返すTryDequeueおよびTryPeekメソッド(DictionaryTryGetValueに似ています)を使用するのが安全な方法です。

using System;
using System.Collections.Generic;

public class QueueTryDequeueExample
{
    public static void Main()
    {
        var taskQueue = new Queue<int>();
        taskQueue.Enqueue(900);

        // 1. 成功する TryDequeue
        if (taskQueue.TryDequeue(out int dequeuedTask))
        {
            Console.WriteLine($"Dequeue 成功: {dequeuedTask}"); // 900
        }

        // 2. キューは空になった
        // 3. 失敗する TryDequeue (例外は発生しない)
        if (taskQueue.TryDequeue(out int failedTask))
        {
            Console.WriteLine($"Dequeue 成功: {failedTask}");
        }
        else
        {
            Console.WriteLine("Dequeue 失敗: キューは空です。");
        }
    }
}

出力結果:

Dequeue 成功: 900
Dequeue 失敗: キューは空です。

まとめ

Queue<T>は、C#で**FIFO(先入れ先出し)**のロジックを実装するための専用コレクションです。

  • 追加: Enqueue(item)(末尾に追加)
  • 削除と取得: Dequeue()(先頭から取得)
  • 参照のみ: Peek()(先頭を参照)

DequeuePeekはキューが空だと例外をスローするため、Count > 0でチェックするか、TryDequeue / TryPeekメソッドを使用することで、安全に操作できます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次