2013-06-16T18:51:48の更新内容

programming/netfx/collections/2_generic_5_2_queue/index.wiki.txt

current previous
1,6 1,6
 
${smdncms:title,ジェネリックコレクション(6) Queue}
${smdncms:title,ジェネリックコレクション(6) Queue}
 
${smdncms:header_title,ジェネリックコレクション その6 Queue (System.Collections.Generic)}
${smdncms:header_title,ジェネリックコレクション その6 Queue (System.Collections.Generic)}
~
${smdncms:keywords,System.Collections.Generic,Queue,キュー,FIFO}
${smdncms:keywords,System.Collections.Generic,Stack,Queue}
 
${smdncms:document_versions,codelang=cs,codelang=vb}
${smdncms:document_versions,codelang=cs,codelang=vb}
 

        

        
 
#navi(..)
#navi(..)
11,20 11,7
 
#googleadunit(banner)
#googleadunit(banner)
 

        

        
 
*Queue [#Queue]
*Queue [#Queue]
~
&msdn(netfx,type,System.Collections.Generic.Queue`1){System.Collections.Generic.Queueクラス};は、先入れ先出し(FIFO: First-In, First-Out)のデータ構造を持つ''キュー''を提供するコレクションクラスです。
&msdn(netfx,type,System.Collections.Generic.Queue`1){System.Collections.Generic.Queueクラス};は[[System.Collections.Queue>programming/netfx/collections/1_nongeneric_4_stack_queue#Queue]]に相当するジェネリックコレクションです。 基本的な操作は非ジェネリックなQueueと同じです。 すべてのメソッドが厳密に型指定されている以外、大きな違いはありません。
+

          
+
**基本的な操作
+
キューでは二つの操作''エンキュー''と''デキュー''が定義されます。 ''エンキュー''はキューの''末尾に''要素を追加する操作で、''デキュー''はキューの''先頭から''要素を取り出す操作です。 この二つの操作により''先入れ先出し''のデータ構造が実現されます。 待ち行列の''最後尾に''一人並べる作業が''エンキュー''、待ち行列の''先頭から''一人引き抜く作業が''デキュー''に相当するとイメージするとよいと思います。
+

          
+
Queueクラスに要素を追加する''エンキュー''の操作は&msdn(netfx,member,System.Collections.Generic.Queue`1.Enqueue){Enqueueメソッド};、Queueから要素を取り出す''デキュー''の操作は&msdn(netfx,member,System.Collections.Generic.Queue`1.Dequeue){Dequeueメソッド};で行います。 Queueから要素を''デキュー''すると、取り出した要素はQueueから削除されます。
+

          
+
#image(queue.png,nopopup,キュー)
+

          
+
[[Listクラス>programming/netfx/collections/2_generic_1_list]]や[[Dictionaryクラス>programming/netfx/collections/2_generic_2_dictionary]]とは異なり、Queueクラスでは要素が格納された順序が大きな意味を持ちます。 Queueに格納される要素は格納された順に並べられ、格納された後はその順序を並べ替えることはできません。 また、最初(または最後)に格納された要素のみに着目するため、インデックスを指定した要素へのアクセス(ランダムアクセス)はできません。
+

          
+
Queueに現在いくつの要素が含まれているかを知るには&msdn(netfx,member,System.Collections.Generic.Queue`1.Count){Countプロパティ};を参照します。 [[List>programming/netfx/collections/2_generic_1_list]]などと同様、Queueは可変長のコレクションであるため任意の数の要素をエンキューできます。 エンキューの際、Queue内部の容量は必要に応じて自動的に拡充されます。 デキューの際に要素数が減っても、Queue内部で確保されている容量が減ることはありません。
+

          
+
次の例では、5つの要素をQueueにエンキューし、その後Queueが空になるまでデキューしています。 キューでは一番最初に入れた要素は一番始めに取り出される(First-In, First-Out)という特性上、要素を入れた順番と同じ順番で表示されている点に注目してください。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
44,198 31,33
 
    q.Enqueue("Dave");
    q.Enqueue("Dave");
 
    q.Enqueue("Eve");
    q.Enqueue("Eve");
 

        

        
~
    // Queueが空になるまで内容をDequeue
    Console.WriteLine("Count: {0}", q.Count);
+
    while (0 < q.Count)
+
    {
+
      Console.WriteLine(q.Dequeue());
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

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

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

          
+
    ' Queueが空になるまで内容をDequeue
+
    While 0 < q.Count
+
      Console.WriteLine(q.Dequeue())
+
    End While
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
Alice
+
Bob
+
Charlie
+
Dave
+
Eve
+
}}
+

          
+
&msdn(netfx,member,System.Collections.Generic.Queue`1.Peek){Peekメソッド};を使うと、Queueの内容はそのままで(Queueから削除せずに)先頭にある要素を取得できます。 Queueの内容が空の場合にDequeueメソッドやPeekメソッドを呼び出すと、null/Nothingが返されるのではなく例外&msdn(netfx,type,System.InvalidOperationException){InvalidOperationException};がスローされます。 従って、戻り値を見てQueueが空になったかどうかを判断することはできません。
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Queue<string> q = new Queue<string>();
+

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

        

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

        

        
~
    // Queueから要素を5つDequeue (Queueの要素数は3なので、途中で例外がスローされる)
    Console.WriteLine("Count: {0}", q.Count);
+
    for (int i = 0; i < 5; i++)
+
    {
+
      Console.WriteLine("Dequeue: {0}", q.Dequeue());
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
 

        

        
~
Class Sample
    // Queueの先頭にある要素をDequeue
~
  Shared Sub Main()
    Console.WriteLine("Dequeue: {0}", q.Dequeue());
~
    Dim q As New Queue(Of String)()
    Console.WriteLine("Dequeue: {0}", q.Dequeue());
 

        

        
~
    ' Queueに要素をEnqueue
    Console.WriteLine("Count: {0}", q.Count);
+
    q.Enqueue("Alice")
+
    q.Enqueue("Bob")
+
    q.Enqueue("Charlie")
+

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

          
+
    ' Queueから要素を5つDequeue (Queueの要素数は3なので、途中で例外がスローされる)
+
    For i As Integer = 0 To 4
+
      Console.WriteLine("Dequeue: {0}", q.Dequeue())
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
Peek: Alice
+
Dequeue: Alice
+
Dequeue: Bob
+
Dequeue: Charlie
+

          
+
Unhandled Exception:
+
System.InvalidOperationException: Operation is not valid due to the current state of the object
+
  at System.Collections.Generic.Queue`1[System.String].Peek () [0x00000] in <filename unknown>:0 
+
  at System.Collections.Generic.Queue`1[System.String].Dequeue () [0x00000] in <filename unknown>:0 
+
  at Sample.Main () [0x00000] in <filename unknown>:0 
+
}}
+

          
+
Queueに指定した内容の要素が含まれているか調べるには、&msdn(netfx,member,System.Collections.Generic.Queue`1.Contains){Containsメソッド};を使います。 ただし、このメソッドでは[[IEqualityComparer>programming/netfx/comparison/1_equation#IEqualityComparer]]を指定できないため、[[Dictionaryのように大文字小文字の違いを無視して比較する>programming/netfx/collections/2_generic_2_dictionary#Dictionary_EqualityComparer]]といったことはできません。 そういった比較条件を指定した上で要素が含まれているかを調べるには、LINQの拡張メソッド&msdn(netfx,member,System.Linq.Enumerable.Contains){Contains};などを使う必要があります。
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+
using System.Linq;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Queue<string> q = new Queue<string>();
+

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

          
+
    // Queueに"CHARLIE"が含まれているか
+
    Console.WriteLine(q.Contains("CHARLIE"));
 

        

        
~
    // Queueに"CHARLIE"が含まれているか
    // Queueに"Alice", "Eve"が含まれるか調べる
~
    // (LINQのContainsメソッドを使い、大文字小文字の違いを無視して調べる)
    Console.WriteLine(q.Contains("Alice"));
~
    Console.WriteLine(q.Contains("CHARLIE", StringComparer.OrdinalIgnoreCase));
    Console.WriteLine(q.Contains("Eve"));
~
  }

          
~
}
    // Queueに"Fran", "Gordon"をEnqueue
~
}}
    q.Enqueue("Fran");
~
#tabpage(codelang=vb)
    q.Enqueue("Gordon");
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+
Imports System.Linq
 

        

        
~
Class Sample
    Console.WriteLine();
+
  Shared Sub Main()
+
    Dim q As New Queue(Of String)()
+

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

          
+
    ' Queueに"CHARLIE"が含まれているか
+
    Console.WriteLine(q.Contains("CHARLIE"))
+

          
+
    ' Queueに"CHARLIE"が含まれているか
+
    ' (LINQのContainsメソッドを使い、大文字小文字の違いを無視して調べる)
+
    Console.WriteLine(q.Contains("CHARLIE", StringComparer.OrdinalIgnoreCase))
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
False
+
True
+
}}
+

          
+
Queueには同一の要素を複数格納したり、null/Nothingを格納することもできます。
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Queue<string> q = new Queue<string>();
+

          
+
    q.Enqueue("Alice");
+
    q.Enqueue("Bob");
+
    q.Enqueue(null); // nullをEnqueue
+
    q.Enqueue("Alice"); // 同一の要素をEnqueue
 

        

        
 
    // Queueが空になるまで内容をDequeue
    // Queueが空になるまで内容をDequeue
 
    while (0 < q.Count)
    while (0 < q.Count)
 
    {
    {
~
      string e = q.Dequeue();
      Console.WriteLine(q.Dequeue());
+

          
+
      Console.WriteLine(e ?? "(null)");
 
    }
    }
 
  }
  }
 
}
}
249,258 71,37
 
  Shared Sub Main()
  Shared Sub Main()
 
    Dim q As New Queue(Of String)()
    Dim q As New Queue(Of String)()
 

        

        
+
    q.Enqueue("Alice")
+
    q.Enqueue("Bob")
+
    q.Enqueue(Nothing) ' NothingをEnqueue
+
    q.Enqueue("Alice") ' 同一の要素をEnqueue
+

          
+
    ' Queueが空になるまで内容をDequeue
+
    While 0 < q.Count
+
      Dim e As String = q.Dequeue()
+

          
+
      If e Is Nothing Then
+
        Console.WriteLine("(Nothing)")
+
      Else
+
        Console.WriteLine(e)
+
      End If
+
    End While
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
Alice
+
Bob
+
(null)
+
Alice
+
}}
+

          
+
Queueの内容を空にするには、&msdn(netfx,member,System.Collections.Generic.Queue`1.Clear){Clearメソッド};を使います。 &msdn(netfx,member,System.Collections.Generic.Queue`1.TrimExcess){TrimExcessメソッド};を呼び出すと、Queueが内部的に確保しているバッファを最小化することができます。 Clearメソッドで空にした後TrimExcessメソッドを呼び出すと、Queueを初期状態に戻すことができます。 なお、&msdn(netfx,member,System.Collections.Generic.List`1.Capacity){List.Capacity};のようなプロパティはQueueには用意されていないため、実際にQueueが保持しているバッファの容量を知ることはできません。
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Queue<string> q = new Queue<string>();
+

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

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

          
+
    // Queueの内容をクリア
+
    q.Clear();
+

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

          
+
    // Queueが確保しているバッファを縮小
+
    q.TrimExcess();
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

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

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

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

          
+
    ' Queueの内容をクリア
+
    q.Clear()
+

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

          
+
    ' Queueが確保しているバッファを縮小
+
    q.TrimExcess()
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
Count = 3
+
Count = 0
+
}}
+

          
+

          
+
**列挙操作 [#Queue_Enumeration]
+
QueueはIEnumerable<T>を実装しているためforeach文による列挙ができるようになっていますが、インデクサはサポートされないのでfor文による列挙はできません。 foreach文による列挙を行う場合は、''Enqueueした順・Dequeueするときと同じ順''で列挙されます。 Queueを列挙しても当然Dequeue操作とは異なり要素の削除は行われません。
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Queue<string> q = new Queue<string>();
+

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

          
+
    // foreachでQueueの内容を列挙
+
    foreach (string e in q)
+
    {
+
      Console.WriteLine(e);
+
    }
+

          
+
    Console.WriteLine("Count: {0}", q.Count);
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

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

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

        

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

          
 
    Console.WriteLine("Count: {0}", q.Count)
    Console.WriteLine("Count: {0}", q.Count)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
~
#prompt(実行結果){{
    ' Queueの先頭にある要素をPeek
~
Alice
    Console.WriteLine("Peek: {0}", q.Peek())
+
Bob
+
Charlie
+
Dave
+
Eve
+
Count: 5
+
}}
 

        

        
~
for文での列挙を行うために[[Queueを配列に変換する>#Queue_ToArray_CopyTo]]ことができます。 単にインデックス付きでの列挙を行いたいだけであれば、LINQの拡張メソッド&msdn(netfx,member,System.Linq.Enumerable.Select){Select};を使って次のようにすることもできます。
    Console.WriteLine("Count: {0}", q.Count)
 

        

        
~
#tabpage(codelang=cs)
    ' Queueの先頭にある要素をDequeue
~
#code{{
    Console.WriteLine("Dequeue: {0}", q.Dequeue())
~
using System;
    Console.WriteLine("Dequeue: {0}", q.Dequeue())
+
using System.Collections.Generic;
+
using System.Linq;
 

        

        
~
class Sample
    Console.WriteLine("Count: {0}", q.Count)
+
{
+
  static void Main()
+
  {
+
    Queue<string> q = new Queue<string>();
 

        

        
~
    q.Enqueue("Alice");
    ' Queueに"Alice", "Eve"が含まれるか調べる
~
    q.Enqueue("Bob");
    Console.WriteLine(q.Contains("Alice"))
~
    q.Enqueue("Charlie");
    Console.WriteLine(q.Contains("Eve"))
~
    q.Enqueue("Dave");

          
~
    q.Enqueue("Eve");
    ' Queueに"Fran", "Gordon"をEnqueue
-
    q.Enqueue("Fran")
-
    q.Enqueue("Gordon")
 

        

        
~
    // Selectメソッドを使ってQueueの要素をインデックス付きで列挙する
    Console.WriteLine()
+
    foreach (var pair in q.Select((e, i) => new {Element = e, Index = i}))
+
    {
+
      Console.WriteLine("{0} => {1}", pair.Index, pair.Element);
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Option Infer On
+

          
+
Imports System
+
Imports System.Collections.Generic
+
Imports System.Linq
+

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

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

          
+
    ' Selectメソッドを使ってQueueの要素をインデックス付きで列挙する
+
    For Each pair In q.Select(Function(e, i)
+
      Return New With {.Element = e, .Index = i}
+
    End Function)
+
      Console.WriteLine("{0} => {1}", pair.Index, pair.Element)
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
0 => Alice
+
1 => Bob
+
2 => Charlie
+
3 => Dave
+
4 => Eve
+
}}
+

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

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

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

          
+
    while (0 < q.Count)
+
    {
+
      Console.WriteLine(q.Dequeue());
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

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

        

        
-
    ' Queueが空になるまで内容をDequeue
 
    While 0 < q.Count
    While 0 < q.Count
 
      Console.WriteLine(q.Dequeue())
      Console.WriteLine(q.Dequeue())
 
    End While
    End While
510,174 111,20
 
#tabpage-end
#tabpage-end
 

        

        
 
#prompt(実行結果){{
#prompt(実行結果){{
~
Alice
Count: 5
~
Bob
Peek: Alice
-
Count: 5
-
Dequeue: Alice
-
Dequeue: Bob
-
Count: 3
-
False
-
True
-

          
 
Charlie
Charlie
 
Dave
Dave
 
Eve
Eve
~
}}
Fran
~

          
Gordon
+
**配列への変換・コピー [#Queue_ToArray_CopyTo]
+
Queueから配列へ変換する場合には&msdn(netfx,member,System.Collections.Generic.Queue`1.ToArray){ToArrayメソッド};や&msdn(netfx,member,System.Collections.Generic.Queue`1.CopyTo){CopyToメソッド};が使えます。 ToArrayメソッドではQueueの内容を配列に変換したものが得られ、CopyToメソッドではQueueの内容を既存の配列にコピーします。 変換・コピーした後の配列の内容は、[[列挙操作を行った場合>#Queue_Enumeration]]と同様にQueueの内容を一つずつDequeueした場合と同じ順序になります。 当然、変換・コピーの前後でQueueの内容は変化しません。
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Queue<string> q = new Queue<string>();
+

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

          
+
    // 配列に変換
+
    Console.WriteLine("[ToArray]");
+

          
+
    string[] arr1 = q.ToArray();
+

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

          
+
    // 配列にコピー
+
    Console.WriteLine("[CopyTo]");
+

          
+
    string[] arr2 = new string[q.Count];
+

          
+
    q.CopyTo(arr2, 0);
+

          
+
    for (int i = 0; i < arr2.Length; i++)
+
    {
+
      Console.WriteLine("arr2[{0}] => {1}", i, arr2[i]);
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

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

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

          
+
    ' 配列に変換
+
    Console.WriteLine("[ToArray]")
+

          
+
    Dim arr1() As String = q.ToArray()
+

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

          
+
    ' 配列にコピー
+
    Console.WriteLine("[CopyTo]")
+

          
+
    Dim arr2(q.Count - 1) As String
+

          
+
    q.CopyTo(arr2, 0)
+

          
+
    For i As Integer = 0 To arr2.Length - 1
+
      Console.WriteLine("arr2({0}) => {1}", i, arr2(i))
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
[ToArray]
+
arr1[0] => Alice
+
arr1[1] => Bob
+
arr1[2] => Charlie
+
arr1[3] => Dave
+
arr1[4] => Eve
+
[CopyTo]
+
arr2[0] => Alice
+
arr2[1] => Bob
+
arr2[2] => Charlie
+
arr2[3] => Dave
+
arr2[4] => Eve
+
}}
+

          
+
Queueの一部分のみを配列として取得するメソッドは用意されていません。 そのため、全部を配列に変換した後必要な部分だけを抜き出して使うか、次のようにLINQの拡張メソッド&msdn(netfx,member,System.Linq.Enumerable.Skip){Skip};および&msdn(netfx,member,System.Linq.Enumerable.Take){Take};を組み合わせて一部分のみを取得します。
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+
using System.Linq;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Queue<string> q = new Queue<string>();
+

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

          
+
    // Queueの1番目から3つ分を配列に変換
+
    // (Queueから要素1つ分をSkip、そこから要素3つをTake、その結果をToArray)
+
    string[] arr = q.Skip(1).Take(3).ToArray();
+

          
+
    for (int i = 0; i < arr.Length; i++)
+
    {
+
      Console.WriteLine("arr[{0}] => {1}", i, arr[i]);
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+
Imports System.Linq
+

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

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

          
+
    ' Queueの1番目から3つ分を配列に変換
+
    ' (Queueから要素1つ分をSkip、そこから要素3つをTake、その結果をToArray)
+
    Dim arr() As String = q.Skip(1).Take(3).ToArray()
+

          
+
    For i As Integer = 0 To arr.Length - 1
+
      Console.WriteLine("arr({0}) => {1}", i, arr(i))
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
arr[0] => Bob
+
arr[1] => Charlie
+
arr[2] => Dave
 
}}
}}
 

        

        
 
#navi(..)
#navi(..)

programming/netfx/collections/2_generic_5_1_stack/index.wiki.txt

current previous
1,6 1,6
 
${smdncms:title,ジェネリックコレクション(5) Stack}
${smdncms:title,ジェネリックコレクション(5) Stack}
 
${smdncms:header_title,ジェネリックコレクション その5 Stack (System.Collections.Generic)}
${smdncms:header_title,ジェネリックコレクション その5 Stack (System.Collections.Generic)}
~
${smdncms:keywords,System.Collections.Generic,Stack,スタック,LIFO}
${smdncms:keywords,System.Collections.Generic,Stack}
 
${smdncms:document_versions,codelang=cs,codelang=vb}
${smdncms:document_versions,codelang=cs,codelang=vb}
 

        

        
 
#navi(..)
#navi(..)
11,20 11,7
 
#googleadunit(banner)
#googleadunit(banner)
 

        

        
 
*Stack [#Stack]
*Stack [#Stack]
~
&msdn(netfx,type,System.Collections.Generic.Stack`1){System.Collections.Generic.Stackクラス};は、後入れ先出し(LIFO: Last-In, First-Out)のデータ構造を持つ''スタック''を提供するコレクションクラスです。
&msdn(netfx,type,System.Collections.Generic.Stack`1){System.Collections.Generic.Stackクラス};は[[System.Collections.Stack>programming/netfx/collections/1_nongeneric_4_stack_queue#Stack]]に相当するジェネリックコレクションです。 基本的な操作は非ジェネリックなStackと同じです。 すべてのメソッドが厳密に型指定されている以外、大きな違いはありません。
+

          
+
**基本的な操作
+
スタックでは二つの操作''プッシュ''と''ポップ''が定義されます。 ''プッシュ''はスタックの''先頭に''要素を追加する操作で、''ポップ''はスタックの''先頭から''要素を取り出す操作です。 この二つの操作により''後入れ先出し''のデータ構造が実現されます。 本を一冊ずつ''上に''積んでいく作業が''プッシュ''、積まれた本を一冊ずつ''上から''取っていく作業が''ポップ''に相当するとイメージするとよいと思います。
+

          
+
Stackクラスに要素を追加する''プッシュ''の操作は&msdn(netfx,member,System.Collections.Generic.Stack`1.Push){Pushメソッド};、Stackから要素を取り出す''ポップ''の操作は&msdn(netfx,member,System.Collections.Generic.Stack`1.Pop){Popメソッド};で行います。 Stackから要素を''ポップ''すると、取り出した要素はStackから削除されます。
+

          
+
#image(stack.png,nopopup,スタック)
+

          
+
[[Listクラス>programming/netfx/collections/2_generic_1_list]]や[[Dictionaryクラス>programming/netfx/collections/2_generic_2_dictionary]]とは異なり、Stackクラスでは要素が格納された順序が大きな意味を持ちます。 Stackに格納される要素は格納された順に並べられ、格納された後はその順序を並べ替えることはできません。 また、最初(または最後)に格納された要素のみに着目するため、インデックスを指定した要素へのアクセス(ランダムアクセス)はできません。
+

          
+
Stackに現在いくつの要素が含まれているかを知るには&msdn(netfx,member,System.Collections.Generic.Stack`1.Count){Countプロパティ};を参照します。 [[List>programming/netfx/collections/2_generic_1_list]]などと同様、Stackは可変長のコレクションであるため任意の数の要素をプッシュできます。 プッシュの際、Stack内部の容量は必要に応じて自動的に拡充されます。 ポップの際に要素数が減っても、Stack内部で確保されている容量が減ることはありません。
+

          
+
次の例では、5つの要素をStackにプッシュし、その後Stackが空になるまでポップしています。 スタックでは一番最後に入れた要素は一番始めに取り出される(Last-In, First-Out)という特性上、要素を入れた順番とは逆の順番で表示されている点に注目してください。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
44,201 31,33
 
    s.Push("Dave");
    s.Push("Dave");
 
    s.Push("Eve");
    s.Push("Eve");
 

        

        
~
    // Stackが空になるまで内容をPop
    Console.WriteLine("Count: {0}", s.Count);
+
    while (0 < s.Count)
+
    {
+
      string e = s.Pop();
+

          
+
      Console.WriteLine(e);
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim s As New Stack(Of String)()
+

          
+
    ' Stackに要素をPush
+
    s.Push("Alice")
+
    s.Push("Bob")
+
    s.Push("Charlie")
+
    s.Push("Dave")
+
    s.Push("Eve")
+

          
+
    ' Stackが空になるまで内容をPop
+
    While 0 < s.Count
+
      Dim e As String = s.Pop()
+

          
+
      Console.WriteLine(e)
+
    End While
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
Eve
+
Dave
+
Charlie
+
Bob
+
Alice
+
}}
+

          
+
&msdn(netfx,member,System.Collections.Generic.Stack`1.Peek){Peekメソッド};を使うと、Stackの内容はそのままで(Stackから削除せずに)先頭にある要素を取得できます。 Stackの内容が空の場合にPopメソッドやPeekメソッドを呼び出すと、null/Nothingが返されるのではなく例外&msdn(netfx,type,System.InvalidOperationException){InvalidOperationException};がスローされます。 従って、戻り値を見てStackが空になったかどうかを判断することはできません。
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Stack<string> s = new Stack<string>();
+

          
+
    // Stackに要素をPush
+
    s.Push("Alice");
+
    s.Push("Bob");
+
    s.Push("Charlie");
 

        

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

        

        
~
    // Stackから要素を5つPop (Stackの要素数は3なので、途中で例外がスローされる)
    Console.WriteLine("Count: {0}", s.Count);
+
    for (int i = 0; i < 5; i++)
+
    {
+
      Console.WriteLine("Pop: {0}", s.Pop());
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
 

        

        
~
Class Sample
    // Stackの先頭にある要素をPop
~
  Shared Sub Main()
    Console.WriteLine("Pop: {0}", s.Pop());
~
    Dim s As New Stack(Of String)()
    Console.WriteLine("Pop: {0}", s.Pop());
 

        

        
~
    ' Stackに要素をPush
    Console.WriteLine("Count: {0}", s.Count);
+
    s.Push("Alice")
+
    s.Push("Bob")
+
    s.Push("Charlie")
+

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

          
+
    ' Stackから要素を5つPop (Stackの要素数は3なので、途中で例外がスローされる)
+
    For i As Integer = 0 To 4
+
      Console.WriteLine("Pop: {0}", s.Pop())
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
Peek: Charlie
+
Pop: Charlie
+
Pop: Bob
+
Pop: Alice
+

          
+
Unhandled Exception:
+
System.InvalidOperationException: Operation is not valid due to the current state of the object
+
  at System.Collections.Generic.Stack`1[System.String].Pop () [0x00000] in <filename unknown>:0 
+
  at Sample.Main () [0x00000] in <filename unknown>:0 
+
}}
+

          
+
Stackに指定した内容の要素が含まれているか調べるには、&msdn(netfx,member,System.Collections.Generic.Stack`1.Contains){Containsメソッド};を使います。 ただし、このメソッドでは[[IEqualityComparer>programming/netfx/comparison/1_equation#IEqualityComparer]]を指定できないため、[[Dictionaryのように大文字小文字の違いを無視して比較する>programming/netfx/collections/2_generic_2_dictionary#Dictionary_EqualityComparer]]といったことはできません。 そういった比較条件を指定した上で要素が含まれているかを調べるには、LINQの拡張メソッド&msdn(netfx,member,System.Linq.Enumerable.Contains){Contains};などを使う必要があります。
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+
using System.Linq;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Stack<string> s = new Stack<string>();
+

          
+
    // Stackに要素をPush
+
    s.Push("Alice");
+
    s.Push("Bob");
+
    s.Push("Charlie");
+

          
+
    // Stackに"CHARLIE"が含まれているか
+
    Console.WriteLine(s.Contains("CHARLIE"));
+

          
+
    // Stackに"CHARLIE"が含まれているか
+
    // (LINQのContainsメソッドを使い、大文字小文字の違いを無視して調べる)
+
    Console.WriteLine(s.Contains("CHARLIE", StringComparer.OrdinalIgnoreCase));
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+
Imports System.Linq
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim s As New Stack(Of String)()
+

          
+
    ' Stackに要素をPush
+
    s.Push("Alice")
+
    s.Push("Bob")
+
    s.Push("Charlie")
+

          
+
    ' Stackに"CHARLIE"が含まれているか
+
    Console.WriteLine(s.Contains("CHARLIE"))
+

          
+
    ' Stackに"CHARLIE"が含まれているか
+
    ' (LINQのContainsメソッドを使い、大文字小文字の違いを無視して調べる)
+
    Console.WriteLine(s.Contains("CHARLIE", StringComparer.OrdinalIgnoreCase))
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
False
+
True
+
}}
+

          
+
Stackには同一の要素を複数格納したり、null/Nothingを格納することもできます。
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
 

        

        
~
class Sample
    // Stackに"Alice", "Eve"が含まれるか調べる
~
{
    Console.WriteLine(s.Contains("Alice"));
~
  static void Main()
    Console.WriteLine(s.Contains("Eve"));
~
  {

          
~
    Stack<string> s = new Stack<string>();
    // Stackに"Fran", "Gordon"をPush
-
    s.Push("Fran");
-
    s.Push("Gordon");
 

        

        
~
    s.Push("Alice");
    Console.WriteLine();
+
    s.Push("Bob");
+
    s.Push(null); // nullをPush
+
    s.Push("Alice"); // 同一の要素をPush
 

        

        
 
    // Stackが空になるまで内容をPop
    // Stackが空になるまで内容をPop
 
    while (0 < s.Count)
    while (0 < s.Count)
 
    {
    {
~
      string e = s.Pop();
      Console.WriteLine(s.Pop());
+

          
+
      Console.WriteLine(e ?? "(null)");
 
    }
    }
 
  }
  }
 
}
}
252,257 71,37
 
  Shared Sub Main()
  Shared Sub Main()
 
    Dim s As New Stack(Of String)()
    Dim s As New Stack(Of String)()
 

        

        
~
    s.Push("Alice")
    ' Stackに要素をPush
+
    s.Push("Bob")
+
    s.Push(Nothing) ' NothingをPush
+
    s.Push("Alice") ' 同一の要素をPush
+

          
+
    ' Stackが空になるまで内容をPop
+
    While 0 < s.Count
+
      Dim e As String = s.Pop()
+

          
+
      If e Is Nothing Then
+
        Console.WriteLine("(Nothing)")
+
      Else
+
        Console.WriteLine(e)
+
      End If
+
    End While
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
Alice
+
(null)
+
Bob
+
Alice
+
}}
+

          
+
Stackの内容を空にするには、&msdn(netfx,member,System.Collections.Generic.Stack`1.Clear){Clearメソッド};を使います。 &msdn(netfx,member,System.Collections.Generic.Stack`1.TrimExcess){TrimExcessメソッド};を呼び出すと、Stackが内部的に確保しているバッファを最小化することができます。 Clearメソッドで空にした後TrimExcessメソッドを呼び出すと、Stackを初期状態に戻すことができます。 なお、&msdn(netfx,member,System.Collections.Generic.List`1.Capacity){List.Capacity};のようなプロパティはStackには用意されていないため、実際にStackが保持しているバッファの容量を知ることはできません。
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Stack<string> s = new Stack<string>();
+

          
+
    s.Push("Alice");
+
    s.Push("Bob");
+
    s.Push("Charlie");
+

          
+
    Console.WriteLine("Count = {0}", s.Count);
+

          
+
    // Stackの内容をクリア
+
    s.Clear();
+

          
+
    Console.WriteLine("Count = {0}", s.Count);
+

          
+
    // Stackが確保しているバッファを縮小
+
    s.TrimExcess();
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim s As New Stack(Of String)()
+

          
+
    s.Push("Alice")
+
    s.Push("Bob")
+
    s.Push("Charlie")
+

          
+
    Console.WriteLine("Count = {0}", s.Count)
+

          
+
    ' Stackの内容をクリア
+
    s.Clear()
+

          
+
    Console.WriteLine("Count = {0}", s.Count)
+

          
+
    ' Stackが確保しているバッファを縮小
+
    s.TrimExcess()
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
Count = 3
+
Count = 0
+
}}
+

          
+
**列挙操作 [#Stack_Enumeration]
+
StackはIEnumerable<T>を実装しているためforeach文による列挙ができるようになっていますが、インデクサはサポートされないのでfor文による列挙はできません。 foreach文による列挙を行う場合は、''Pushした順とは逆''、''Popするときと同じ順''で列挙されます。 Stackを列挙しても当然Pop操作とは異なり要素の削除は行われません。
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Stack<string> s = new Stack<string>();
+

          
+
    s.Push("Alice");
+
    s.Push("Bob");
+
    s.Push("Charlie");
+
    s.Push("Dave");
+
    s.Push("Eve");
+

          
+
    // foreachでStackの内容を列挙
+
    foreach (string e in s)
+
    {
+
      Console.WriteLine(e);
+
    }
+

          
+
    Console.WriteLine("Count: {0}", s.Count);
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim s As New Stack(Of String)()
+

          
 
    s.Push("Alice")
    s.Push("Alice")
 
    s.Push("Bob")
    s.Push("Bob")
 
    s.Push("Charlie")
    s.Push("Charlie")
 
    s.Push("Dave")
    s.Push("Dave")
 
    s.Push("Eve")
    s.Push("Eve")
 

        

        
+
    ' For EachでStackの内容を列挙
+
    For Each e As String In s
+
      Console.WriteLine(e)
+
    Next
+

          
 
    Console.WriteLine("Count: {0}", s.Count)
    Console.WriteLine("Count: {0}", s.Count)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
~
#prompt(実行結果){{
    ' Stackの先頭にある要素をPeek
~
Eve
    Console.WriteLine("Peek: {0}", s.Peek())
+
Dave
+
Charlie
+
Bob
+
Alice
+
Count: 5
+
}}
 

        

        
~
for文での列挙を行うために[[Stackを配列に変換する>#Stack_ToArray_CopyTo]]ことができます。 単にインデックス付きでの列挙を行いたいだけであれば、LINQの拡張メソッド&msdn(netfx,member,System.Linq.Enumerable.Select){Select};を使って次のようにすることもできます。
    Console.WriteLine("Count: {0}", s.Count)
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+
using System.Linq;
 

        

        
~
class Sample
    ' Stackの先頭にある要素をPop
~
{
    Console.WriteLine("Pop: {0}", s.Pop())
~
  static void Main()
    Console.WriteLine("Pop: {0}", s.Pop())
+
  {
+
    Stack<string> s = new Stack<string>();
 

        

        
~
    s.Push("Alice");
    Console.WriteLine("Count: {0}", s.Count)
+
    s.Push("Bob");
+
    s.Push("Charlie");
+
    s.Push("Dave");
+
    s.Push("Eve");
+

          
+
    // Selectメソッドを使ってStackの要素をインデックス付きで列挙する
+
    foreach (var pair in s.Select((e, i) => new {Element = e, Index = i}))
+
    {
+
      Console.WriteLine("{0} => {1}", pair.Index, pair.Element);
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code(vb,VB10){{
+
Option Infer On
 

        

        
~
Imports System
    ' Stackに"Alice", "Eve"が含まれるか調べる
~
Imports System.Collections.Generic
    Console.WriteLine(s.Contains("Alice"))
~
Imports System.Linq
    Console.WriteLine(s.Contains("Eve"))
-

          
-
    ' Stackに"Fran", "Gordon"をPush
-
    s.Push("Fran")
-
    s.Push("Gordon")
 

        

        
~
Class Sample
    Console.WriteLine()
+
  Shared Sub Main()
+
    Dim s As New Stack(Of String)()
+

          
+
    s.Push("Alice")
+
    s.Push("Bob")
+
    s.Push("Charlie")
+
    s.Push("Dave")
+
    s.Push("Eve")
+

          
+
    ' Selectメソッドを使ってStackの要素をインデックス付きで列挙する
+
    For Each pair In s.Select(Function(e, i)
+
      Return New With {.Element = e, .Index = i}
+
    End Function)
+
      Console.WriteLine("{0} => {1}", pair.Index, pair.Element)
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
0 => Eve
+
1 => Dave
+
2 => Charlie
+
3 => Bob
+
4 => Alice
+
}}
+

          
+

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

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

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

          
+
    while (0 < s.Count)
+
    {
+
      Console.WriteLine(s.Pop());
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

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

        

        
-
    ' Stackが空になるまで内容をPop
 
    While 0 < s.Count
    While 0 < s.Count
 
      Console.WriteLine(s.Pop())
      Console.WriteLine(s.Pop())
 
    End While
    End While
512,175 111,21
 
#tabpage-end
#tabpage-end
 

        

        
 
#prompt(実行結果){{
#prompt(実行結果){{
~
Eve
Count: 5
~
Dave
Peek: Eve
-
Count: 5
-
Pop: Eve
-
Pop: Dave
-
Count: 3
-
True
-
False
-

          
-
Gordon
-
Fran
 
Charlie
Charlie
 
Bob
Bob
 
Alice
Alice
 
}}
}}
 

        

        
+
**配列への変換・コピー [#Stack_ToArray_CopyTo]
+
Stackから配列へ変換する場合には&msdn(netfx,member,System.Collections.Generic.Stack`1.ToArray){ToArrayメソッド};や&msdn(netfx,member,System.Collections.Generic.Stack`1.CopyTo){CopyToメソッド};が使えます。 ToArrayメソッドではStackの内容を配列に変換したものが得られ、CopyToメソッドではStackの内容を既存の配列にコピーします。 変換・コピーした後の配列の内容は、[[列挙操作を行った場合>#Stack_Enumeration]]と同様にStackの内容を一つずつPopした場合と同じ順序になります。 当然、変換・コピーの前後でStackの内容は変化しません。
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Stack<string> s = new Stack<string>();
+

          
+
    s.Push("Alice");
+
    s.Push("Bob");
+
    s.Push("Charlie");
+
    s.Push("Dave");
+
    s.Push("Eve");
+

          
+
    // 配列に変換
+
    Console.WriteLine("[ToArray]");
+

          
+
    string[] arr1 = s.ToArray();
+

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

          
+
    // 配列にコピー
+
    Console.WriteLine("[CopyTo]");
+

          
+
    string[] arr2 = new string[s.Count];
+

          
+
    s.CopyTo(arr2, 0);
+

          
+
    for (int i = 0; i < arr2.Length; i++)
+
    {
+
      Console.WriteLine("arr2[{0}] => {1}", i, arr2[i]);
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim s As New Stack(Of String)()
+

          
+
    s.Push("Alice")
+
    s.Push("Bob")
+
    s.Push("Charlie")
+
    s.Push("Dave")
+
    s.Push("Eve")
+

          
+
    ' 配列に変換
+
    Console.WriteLine("[ToArray]")
+

          
+
    Dim arr1() As String = s.ToArray()
+

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

          
+
    ' 配列にコピー
+
    Console.WriteLine("[CopyTo]")
+

          
+
    Dim arr2(s.Count - 1) As String
+

          
+
    s.CopyTo(arr2, 0)
+

          
+
    For i As Integer = 0 To arr2.Length - 1
+
      Console.WriteLine("arr2({0}) => {1}", i, arr2(i))
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
[ToArray]
+
arr1[0] => Eve
+
arr1[1] => Dave
+
arr1[2] => Charlie
+
arr1[3] => Bob
+
arr1[4] => Alice
+
[CopyTo]
+
arr2[0] => Eve
+
arr2[1] => Dave
+
arr2[2] => Charlie
+
arr2[3] => Bob
+
arr2[4] => Alice
+
}}
+

          
+
Stackの一部分のみを配列として取得するメソッドは用意されていません。 そのため、全部を配列に変換した後必要な部分だけを抜き出して使うか、次のようにLINQの拡張メソッド&msdn(netfx,member,System.Linq.Enumerable.Skip){Skip};および&msdn(netfx,member,System.Linq.Enumerable.Take){Take};を組み合わせて一部分のみを取得します。
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+
using System.Linq;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Stack<string> s = new Stack<string>();
+

          
+
    s.Push("Alice");
+
    s.Push("Bob");
+
    s.Push("Charlie");
+
    s.Push("Dave");
+
    s.Push("Eve");
+

          
+
    // Stackの1番目から3つ分を配列に変換
+
    // (Stackから要素1つ分をSkip、そこから要素3つをTake、その結果をToArray)
+
    string[] arr = s.Skip(1).Take(3).ToArray();
+

          
+
    for (int i = 0; i < arr.Length; i++)
+
    {
+
      Console.WriteLine("arr[{0}] => {1}", i, arr[i]);
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+
Imports System.Linq
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim s As New Stack(Of String)()
+

          
+
    s.Push("Alice")
+
    s.Push("Bob")
+
    s.Push("Charlie")
+
    s.Push("Dave")
+
    s.Push("Eve")
+

          
+
    ' Stackの1番目から3つ分を配列に変換
+
    ' (Stackから要素1つ分をSkip、そこから要素3つをTake、その結果をToArray)
+
    Dim arr() As String = s.Skip(1).Take(3).ToArray()
+

          
+
    For i As Integer = 0 To arr.Length - 1
+
      Console.WriteLine("arr({0}) => {1}", i, arr(i))
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
arr[0] => Dave
+
arr[1] => Charlie
+
arr[2] => Bob
+
}}
+

          
 
#navi(..)
#navi(..)