2013-08-01T23:23:55の更新内容

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

current previous
125,7 125,6
 
{
{
 
  static void Main()
  static void Main()
 
  {
  {
+
    // 要素数が3(=インデックスの上限が2)のList
 
    List<int> list = new List<int>() {0, 1, 2};
    List<int> list = new List<int>() {0, 1, 2};
 

        

        
 
    // インデックス0の要素に値を設定する
    // インデックス0の要素に値を設定する
145,7 144,6
 

        

        
 
Class Sample
Class Sample
 
  Shared Sub Main()
  Shared Sub Main()
+
    ' 要素数が3(=インデックスの上限が2)のList
 
    Dim list As New List(Of Integer)(New Integer() {0, 1, 2})
    Dim list As New List(Of Integer)(New Integer() {0, 1, 2})
 

        

        
 
    ' インデックス0の要素に値を設定する
    ' インデックス0の要素に値を設定する
313,239 311,6
 
Listをforeach文で列挙している最中に要素の追加や削除などの変更を行おうとすると、例外InvalidOperationExceptionがスローされます。 これを回避するにはforeachの代わりにfor文や[[ForEachメソッド>#List_Enumeartion]]を使うようにします。 詳しくは[[programming/netfx/enumeration]]でも解説していますので適宜参照してください。
Listをforeach文で列挙している最中に要素の追加や削除などの変更を行おうとすると、例外InvalidOperationExceptionがスローされます。 これを回避するにはforeachの代わりにfor文や[[ForEachメソッド>#List_Enumeartion]]を使うようにします。 詳しくは[[programming/netfx/enumeration]]でも解説していますので適宜参照してください。
 

        

        
 

        

        
+
**要素の変更
+
要素を入れ替えて値を変更するには、変更したい要素のインデックスを指定して値を代入します。
+

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

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    // 要素が格納されていない空のListを作成
+
    List<string> list = new List<string>();
+

          
+
    // 要素を追加する
+
    list.Add("Alice");
+
    list.Add("Bob");
+
    list.Add("Charlie");
+

          
+
    Print(list);
+

          
+
    // インデックス1の要素に格納されている値を変更する
+
    list[1] = "Dave";
+

          
+
    Print(list);
+
  }
+

          
+
  static void Print(List<string> list)
+
  {
+
    foreach (string e in list)
+
    {
+
      Console.Write("{0}, ", e);
+
    }
+

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

          
+
Class Sample
+
  Shared Sub Main()
+
    ' 要素が格納されていない空のListを作成
+
    Dim list As New List(Of String)()
+

          
+
    ' 要素を追加する
+
    list.Add("Alice")
+
    list.Add("Bob")
+
    list.Add("Charlie")
+

          
+
    Print(list)
+

          
+
    ' インデックス1の要素に格納されている値を変更する
+
    list(1) = "Dave"
+

          
+
    Print(list)
+
  End Sub
+

          
+
  Shared Sub Print(ByVal list As List(Of String))
+
    For Each e As String In list
+
      Console.Write("{0}, ", e)
+
    Next
+

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

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

          
+
***構造体要素の変更
+
要素に構造体を格納するようにしたListで構造体のプロパティやフィールドだけを変更しようとする場合は注意が必要です。 例えば、次のようなコードはコンパイルエラーとなります。
+

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

          
+
// Listに格納する構造体
+
struct S
+
{
+
  public int F;
+

          
+
  public S(int f)
+
  {
+
    F = f;
+
  }
+
}
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    List<S> list = new List<S>();
+

          
+
    // フィールドFに値3を設定した構造体を格納
+
    list.Add(new S(3));
+

          
+
    // インデックス0の構造体フィールドの値を変更したいが、コンパイルエラーとなる
+
    list[0].F = 16;
+
    // error CS1612: 変数ではないため、'System.Collections.Generic.List<S>.this[int]'の戻り値を変更できません。
+

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

          
+
' Listに格納する構造体
+
Structure S
+
  Public F As Integer
+

          
+
  Public Sub New(ByVal val As Integer)
+
    F = val
+
  End Sub
+
End Structure
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim list As New List(Of S)()
+

          
+
    ' フィールドFに値3を設定した構造体を格納
+
    list.Add(new S(3))
+

          
+
    ' インデックス0の構造体フィールドの値を変更したいが、コンパイルエラーとなる
+
    list(0).F = 16
+
    ' error BC30068: Expression は値であるため、代入式のターゲットにすることはできません。
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
このような操作を行いたい場合は、いったんListから一時変数に構造体をコピーし、値を変更してから再度Listに格納するようにします。
+

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

          
+
// Listに格納する構造体
+
struct S
+
{
+
  public int F;
+

          
+
  public S(int f)
+
  {
+
    F = f;
+
  }
+
}
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    List<S> list = new List<S>();
+

          
+
    // フィールドFに値3を設定した構造体を格納
+
    list.Add(new S(3));
+

          
+
    // Listに格納した構造体フィールドの値を参照
+
    Console.WriteLine("list[0].F = {0}", list[0].F);
+

          
+
    // フィールドの値を変更したい構造体を一時変数にコピーする
+
    S tmp = list[0];
+

          
+
    // 一時変数に代入した構造体のフィールドの値を変更する
+
    tmp.F = 16;
+

          
+
    // 変更した構造体を再度Listに格納する
+
    list[0] = tmp;
+

          
+
    // Listに格納した構造体フィールドの値を参照
+
    Console.WriteLine("list[0].F = {0}", list[0].F);
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
' Listに格納する構造体
+
Structure S
+
  Public F As Integer
+

          
+
  Public Sub New(ByVal val As Integer)
+
    F = val
+
  End Sub
+
End Structure
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim list As New List(Of S)()
+

          
+
    ' フィールドFに値3を設定した構造体を格納
+
    list.Add(new S(3))
+

          
+
    ' Listに格納した構造体フィールドの値を参照
+
    Console.WriteLine("list(0).F = {0}", list(0).F)
+

          
+
    ' フィールドの値を変更したい構造体を一時変数にコピーする
+
    Dim tmp As S = list(0)
+

          
+
    ' 一時変数に代入した構造体のフィールドの値を変更する
+
    tmp.F = 16
+

          
+
    ' 変更した構造体を再度Listに格納する
+
    list(0) = tmp
+

          
+
    ' Listに格納した構造体フィールドの値を参照
+
    Console.WriteLine("list(0).F = {0}", list(0).F)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
list[0].F = 3
+
list[0].F = 16
+
}}
+

          
+
なお、構造体ではなくクラスの場合はこのような操作を行う必要はありません。 この違いは型が値型か参照型かによって決まります。 詳しくは[[programming/netfx/cloning]]を参照してください。
+

          
 
**要素の削除
**要素の削除
 
要素を削除するには&msdn(netfx,member,System.Collections.Generic.List`1.Remove){Removeメソッド};や&msdn(netfx,member,System.Collections.Generic.List`1.RemoveAt){RemoveAtメソッド};を使います。 Removeメソッドでは''削除したい値''を指定し、RemoveAtメソッドでは''削除したい要素のインデックス''を指定します。 Removeメソッドでは、同じ値を持つ要素が複数ある場合、最初に見つかったものが削除されます。
要素を削除するには&msdn(netfx,member,System.Collections.Generic.List`1.Remove){Removeメソッド};や&msdn(netfx,member,System.Collections.Generic.List`1.RemoveAt){RemoveAtメソッド};を使います。 Removeメソッドでは''削除したい値''を指定し、RemoveAtメソッドでは''削除したい要素のインデックス''を指定します。 Removeメソッドでは、同じ値を持つ要素が複数ある場合、最初に見つかったものが削除されます。
 

        

        
717,223 482,6
 
なお、[[Find等のメソッド>#List_Predicate]]を使うと、条件を指定して要素を検索することが出来ます。 また、文字列を格納するリストで大文字小文字を無視した検索をしたい場合などはこれらのメソッドを使う必要があります。
なお、[[Find等のメソッド>#List_Predicate]]を使うと、条件を指定して要素を検索することが出来ます。 また、文字列を格納するリストで大文字小文字を無視した検索をしたい場合などはこれらのメソッドを使う必要があります。
 

        

        
 

        

        
+
**最初の要素・最後の要素
+
ListにはFirstやLastといった最初の要素・最後の要素を参照するプロパティは用意されていません。 そのため、次のように直接インデックスを指定して要素を参照する必要があります。
+

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

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    List<string> list = new List<string>() {"Alice", "Bob", "Charlie", "Dave", "Eve"};
+

          
+
    // 最初の要素(インデックスが0の要素)を取得
+
    Console.WriteLine(list[0]);
+

          
+
    // 最後の要素(インデックスがCount - 1の要素)を取得
+
    Console.WriteLine(list[list.Count - 1]);
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim list As New List(Of String)(New String() {"Alice", "Bob", "Charlie", "Dave", "Eve"})
+

          
+
    ' 最初の要素(インデックスが0の要素)を取得
+
    Console.WriteLine(list(0))
+

          
+
    ' 最後の要素(インデックスがCount - 1の要素)を取得
+
    Console.WriteLine(list(list.Count - 1))
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

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

          
+
LINQの拡張メソッドである&msdn(netfx,member,System.Linq.Enumerable.First){Firstメソッド};と&msdn(netfx,member,System.Linq.Enumerable.Last){Lastメソッド};を使うことでも最初の要素・最後の要素を取得することができます。
+

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

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    List<string> list = new List<string>() {"Alice", "Bob", "Charlie", "Dave", "Eve"};
+

          
+
    // 最初の要素を取得
+
    Console.WriteLine(list.First());
+

          
+
    // 最後の要素を取得
+
    Console.WriteLine(list.Last());
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+
Imports System.Linq
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim list As New List(Of String)(New String() {"Alice", "Bob", "Charlie", "Dave", "Eve"})
+

          
+
    ' 最初の要素を取得
+
    Console.WriteLine(list.First())
+

          
+
    ' 最後の要素を取得
+
    Console.WriteLine(list.Last())
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

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

          
+
常に最初の要素・最後の要素を参照する必要がある場合では、Listではなく[[Stack>programming/netfx/collections/2_generic_5_1_stack]]や[[Queue>programming/netfx/collections/2_generic_5_2_queue]]などのコレクションの方が適切な場合があります。 また、[[LinkedList>programming/netfx/collections/2_generic_4_linkedlist]]では最初の要素・最後の要素を表すFirstプロパティとLastプロパティが用意されています。
+

          
+
**最大の要素・最小の要素
+
ListにはMinやMaxといったコレクション内での最大の値を持つ要素・最小の値を持つ要素を参照するプロパティは用意されていません。 そのため、Listのすべての要素を走査して最大・最小の要素を検索する必要があります。
+

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

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    List<int> list = new List<int>() {0, 4, 2, 5, 3, 1};
+

          
+
    // 最大の要素を取得
+
    int max = 0;
+

          
+
    foreach (int e in list)
+
    {
+
      if (max < e) max = e;
+
    }
+

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

          
+
    // 最小の要素を取得
+
    int min = int.MaxValue;
+

          
+
    foreach (int e in list)
+
    {
+
      if (e < min) min = e;
+
    }
+

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

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim list As New List(Of Integer)(New Integer() {0, 4, 2, 5, 3, 1})
+

          
+
    ' 最大の要素を取得
+
    Dim max As Integer = 0
+

          
+
    For Each e As Integer In list
+
      If max < e Then max = e
+
    Next
+

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

          
+
    ' 最小の要素を取得
+
    Dim min As Integer = Integer.MaxValue
+

          
+
    For Each e As Integer In list
+
      If e < min Then min = e
+
    Next
+

          
+
    Console.WriteLine("min = {0}", min)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
max = 5
+
min = 0
+
}}
+

          
+
LINQの拡張メソッドである&msdn(netfx,member,System.Linq.Enumerable.Max){Maxメソッド};と&msdn(netfx,member,System.Linq.Enumerable.Min){Minメソッド};を使うことでも最大の要素・最小の要素を取得することができます。
+

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

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    List<int> list = new List<int>() {0, 4, 2, 5, 3, 1};
+

          
+
    // 最大の要素を取得
+
    Console.WriteLine("max = {0}", list.Max());
+

          
+
    // 最小の要素を取得
+
    Console.WriteLine("min = {0}", list.Min());
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+
Imports System.Linq
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim list As New List(Of Integer)(New Integer() {0, 4, 2, 5, 3, 1})
+

          
+
    ' 最大の要素を取得
+
    Console.WriteLine("max = {0}", list.Max())
+

          
+
    ' 最小の要素を取得
+
    Console.WriteLine("min = {0}", list.Min())
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
max = 5
+
min = 0
+
}}
+

          
+
[[SortedSet>programming/netfx/collections/2_generic_6_hashset_sortedset]]では、Maxプロパティ・Minプロパティを参照することにより最大の要素・最小の要素を取得することができるようになっています。
+

          
+

          
 
**配列への変換・コピー
**配列への変換・コピー
 
Listを配列に変換する必要がある場合は、&msdn(netfx,member,System.Collections.Generic.List`1.ToArray){ToArrayメソッド};が使えます。 このメソッドでは、現在Listに格納されている内容をコピーした配列を返します。
Listを配列に変換する必要がある場合は、&msdn(netfx,member,System.Collections.Generic.List`1.ToArray){ToArrayメソッド};が使えます。 このメソッドでは、現在Listに格納されている内容をコピーした配列を返します。
 

        

        
970,7 518,7
 

        

        
 
Class Sample
Class Sample
 
  Shared Sub Main()
  Shared Sub Main()
~
    Dim list As New List(Of String)(New String() {"Alice", "Bob", "Charlie", "Dave", "Eve"})
    Dim list As New List(Of String)(New String() {"Alice", "Bob", "Charlie", "Bob", "Alice"})
 

        

        
 
    Dim arr As String()
    Dim arr As String()
 

        

        
993,8 541,8
 
Alice
Alice
 
Bob
Bob
 
Charlie
Charlie
~
Dave
Bob
~
Eve
Alice
 
}}
}}
 

        

        
 
なお、このメソッドでは''簡易コピー''が行われるため、参照型を要素に持つListの場合は参照のみがコピーされます。 簡易コピーについてより詳しくは[[programming/netfx/cloning]]で解説しています。
なお、このメソッドでは''簡易コピー''が行われるため、参照型を要素に持つListの場合は参照のみがコピーされます。 簡易コピーについてより詳しくは[[programming/netfx/cloning]]で解説しています。
1583,320 1131,6
 
evE
evE
 
}}
}}
 

        

        
+
*容量 [#List_Capacity]
+
Listでは、あらかじめListの内部に大きめの配列を用意しておき、そこに要素を格納していくことで可変長配列の機能を実現しています。 そのためListでは、実際にListに格納されている要素数よりも大きい配列が自動的に確保されます。 CountプロパティでList内に含まれる要素数を取得することができるのに対し、&msdn(netfx,member,System.Collections.Generic.List`1.Capacity){Capacityプロパティ};を参照することでList内で確保されている配列の容量を知ることができます。
+

          
+
次の例では、空のListを作成し、1つずつ要素を追加していったときのListの容量の変化を見ています。
+

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

          
+
class Sample {
+
  public static void Main()
+
  {
+
    // 空のListを作成
+
    List<int> list = new List<int>();
+

          
+
    // 現在の要素数とListの容量を表示
+
    Console.WriteLine("Count={0} Capacity={1}", list.Count, list.Capacity);
+

          
+
    // 要素を20個追加する
+
    for (int i = 0; i < 20; i++)
+
    {
+
      list.Add(i);
+

          
+
      // 現在の要素数とListの容量を表示
+
      Console.WriteLine("Count={0} Capacity={1}", list.Count, list.Capacity);
+
    }
+

          
+
    Console.WriteLine();
+

          
+
    // Listを空にする
+
    list.Clear();
+

          
+
    // 現在の要素数とListの容量を表示
+
    Console.WriteLine("Count={0} Capacity={1}", list.Count, list.Capacity);
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
Class Sample
+
  Shared Sub Main()
+
    ' 空のListを作成
+
    Dim list As New List(Of Integer)
+

          
+
    ' 現在の要素数とListの容量を表示
+
    Console.WriteLine("Count={0} Capacity={1}", list.Count, list.Capacity)
+

          
+
    ' 要素を20個追加する
+
    For i As Integer = 0 To 19
+
      list.Add(i)
+

          
+
      ' 現在の要素数とListの容量を表示
+
      Console.WriteLine("Count={0} Capacity={1}", list.Count, list.Capacity)
+
    Next
+

          
+
    Console.WriteLine()
+

          
+
    ' Listを空にする
+
    list.Clear()
+

          
+
    ' 現在の要素数とListの容量を表示
+
    Console.WriteLine("Count={0} Capacity={1}", list.Count, list.Capacity)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
Count=0 Capacity=0
+
Count=1 Capacity=4
+
Count=2 Capacity=4
+
Count=3 Capacity=4
+
Count=4 Capacity=4
+
Count=5 Capacity=8
+
Count=6 Capacity=8
+
Count=7 Capacity=8
+
Count=8 Capacity=8
+
Count=9 Capacity=16
+
Count=10 Capacity=16
+
Count=11 Capacity=16
+
Count=12 Capacity=16
+
Count=13 Capacity=16
+
Count=14 Capacity=16
+
Count=15 Capacity=16
+
Count=16 Capacity=16
+
Count=17 Capacity=32
+
Count=18 Capacity=32
+
Count=19 Capacity=32
+
Count=20 Capacity=32
+

          
+
Count=0 Capacity=32
+
}}
+

          
+
このようにListでは、要素の追加を行う際など必要になった時点で容量を拡張していることがわかります。
+

          
+
この結果からもわかるとおり、Listでは常に格納されている要素数以上の容量を持ちます。 また、Clearメソッドなどによって要素数が減っても一度確保された容量が減ることはありません。 従って、Listに対して多数の要素の追加・削除を行った後には、使われなくなった(必要以上の)領域がそのまま残されることになります。
+

          
+
Listにそれ以上要素を追加する必要がなくなった場合などには、&msdn(netfx,member,System.Collections.Generic.List`1.TrimExcess){TrimExcessメソッド};を使用することで不要な容量を減らすことができます。
+

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

          
+
class Sample {
+
  public static void Main()
+
  {
+
    // 空のListを作成
+
    List<int> list = new List<int>();
+

          
+
    // 1500個の要素を追加
+
    for (int i = 0; i < 1500; i++)
+
    {
+
      list.Add(i);
+
    }
+

          
+
    // 先頭から500個の要素を削除
+
    list.RemoveRange(0, 500);
+

          
+
    // 要素数とListの容量を表示
+
    Console.WriteLine("[before]");
+
    Console.WriteLine("Count={0} Capacity={1}", list.Count, list.Capacity);
+

          
+
    // Listが確保している容量を必要最低限に減らす
+
    list.TrimExcess();
+

          
+
    // 要素数とListの容量を表示
+
    Console.WriteLine("[after]");
+
    Console.WriteLine("Count={0} Capacity={1}", list.Count, list.Capacity);
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
Class Sample
+
  Shared Sub Main()
+
    ' 空のListを作成
+
    Dim list As New List(Of Integer)
+

          
+
    ' 1500個の要素を追加
+
    For i As Integer = 0 To 1500 - 1
+
      list.Add(i)
+
    Next
+

          
+
    ' 先頭から500個の要素を削除
+
    list.RemoveRange(0, 500)
+

          
+
    ' 要素数とListの容量を表示
+
    Console.WriteLine("[before]")
+
    Console.WriteLine("Count={0} Capacity={1}", list.Count, list.Capacity)
+

          
+
    ' Listが確保している容量を必要最低限に減らす
+
    list.TrimExcess()
+

          
+
    ' 要素数とListの容量を表示
+
    Console.WriteLine("[after]")
+
    Console.WriteLine("Count={0} Capacity={1}", list.Count, list.Capacity)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
[before]
+
Count=1000 Capacity=2048
+
[after]
+
Count=1000 Capacity=1000
+
}}
+

          
+
**初期容量
+
Listでは容量の拡張が行われる度に領域の再割当てと要素のコピーが行われます。 そのため、Listに格納される要素の最大数があらかじめ見積もれる場合には、Listの初期容量を指定することにより再割当てとコピーを抑止することができ、パフォーマンスの向上が見込めます。 また、不必要に大きい領域の確保が行われなくなるというメリットもあります。 Listでは、コンストラクタで初期容量を指定してインスタンスを作成することができるようになっています。
+

          
+
次の例では、初期容量を指定しないListと指定したListについて、要素を10000個追加する場合の処理時間の違いを計測しています。
+

          
+
#code(cs){{
+
using System;
+
using System.Collections.Generic;
+
using System.Diagnostics;
+

          
+
class Sample {
+
  private static void Case1()
+
  {
+
    // 空のListを作成
+
    List<int> list = new List<int>();
+

          
+
    // 10000個の要素を追加する場合の処理時間を計測
+
    Stopwatch sw = Stopwatch.StartNew();
+

          
+
    for (int i = 0; i < 10000; i++)
+
    {
+
      list.Add(i);
+
    }
+

          
+
    Console.WriteLine("Count={0} Capacity={1} Elapsed={2}", list.Count, list.Capacity, sw.Elapsed);
+
  }
+

          
+
  private static void Case2()
+
  {
+
    // 初期容量を指定してListを作成
+
    List<int> list = new List<int>(10000);
+

          
+
    // 10000個の要素を追加する場合の処理時間を計測
+
    Stopwatch sw = Stopwatch.StartNew();
+

          
+
    for (int i = 0; i < 10000; i++)
+
    {
+
      list.Add(i);
+
    }
+

          
+
    Console.WriteLine("Count={0} Capacity={1} Elapsed={2}", list.Count, list.Capacity, sw.Elapsed);
+
  }
+

          
+
  public static void Main()
+
  {
+
    // Case1とCase2を5回ずつ試行
+
    Console.WriteLine("Case1");
+
    for (int t = 0; t < 5; t++)
+
    {
+
      Case1();
+
    }
+

          
+
    Console.WriteLine("Case2");
+
    for (int t = 0; t < 5; t++)
+
    {
+
      Case2();
+
    }
+
  }
+
}
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
Case1
+
Count=10000 Capacity=16384 Elapsed=00:00:00.0013732
+
Count=10000 Capacity=16384 Elapsed=00:00:00.0004316
+
Count=10000 Capacity=16384 Elapsed=00:00:00.0001275
+
Count=10000 Capacity=16384 Elapsed=00:00:00.0002532
+
Count=10000 Capacity=16384 Elapsed=00:00:00.0002470
+
Case2
+
Count=10000 Capacity=10000 Elapsed=00:00:00.0000754
+
Count=10000 Capacity=10000 Elapsed=00:00:00.0000750
+
Count=10000 Capacity=10000 Elapsed=00:00:00.0000717
+
Count=10000 Capacity=10000 Elapsed=00:00:00.0000683
+
Count=10000 Capacity=10000 Elapsed=00:00:00.0000891
+
}}
+

          
+
初期容量を指定してListのインスタンスを作成しても、その数の要素数が確保されるわけではありません。 初期容量として指定した値に関わらず、インスタンスを作成した直後の要素数は0となります。
+

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

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    // 初期容量に100を指定してListを作成
+
    List<int> list = new List<int>(100);
+

          
+
    // CountとCapacityを表示
+
    Console.WriteLine("Count = {0}", list.Count);
+
    Console.WriteLine("Capacity = {0}", list.Capacity);
+

          
+
    // インデックス50の要素を設定
+
    // (要素数は0でインデックス50は範囲外のため例外が発生する)
+
    list[50] = 0;
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
Class Sample
+
  Shared Sub Main()
+
    ' 初期容量に100を指定してListを作成
+
    Dim list As New List(Of Integer)(100)
+

          
+
    ' CountとCapacityを表示
+
    Console.WriteLine("Count = {0}", list.Count)
+
    Console.WriteLine("Capacity = {0}", list.Capacity)
+

          
+
    ' インデックス50の要素を設定
+
    ' (要素数は0でインデックス50は範囲外のため例外が発生する)
+
    list(50) = 0
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
Count = 0
+
Capacity = 100
+

          
+
ハンドルされていない例外: System.ArgumentOutOfRangeException: インデックスが範囲を超えています。負でない値で、コレクションのサイズよりも小さくなければなりません。
+
パラメーター名: index
+
   場所 System.Collections.Generic.List`1.set_Item(Int32 index, T value)
+
   場所 Sample.Main()
+
}}
+

          
+

          
+

          
+

          
+

          
+

          
 

        

        
 
*入れ子 [#List_Nest]
*入れ子 [#List_Nest]
 
List<T>は任意の型Tに型付けしたリストを作成できるため、TにList<T>を指定すれば入れ子になったリストList<List<T>>を作成することが出来ます。 例えば可変長のジャグ配列のようなものを作成したい場合は、Listを入れ子にすることで実現できます。 入れ子になったListを列挙する場合、例えばList<List<int>>を列挙すると、List<List<int>>に含まれているList<int>を一つずつ取り出せます。
List<T>は任意の型Tに型付けしたリストを作成できるため、TにList<T>を指定すれば入れ子になったリストList<List<T>>を作成することが出来ます。 例えば可変長のジャグ配列のようなものを作成したい場合は、Listを入れ子にすることで実現できます。 入れ子になったListを列挙する場合、例えばList<List<int>>を列挙すると、List<List<int>>に含まれているList<int>を一つずつ取り出せます。