C# - よく使うクラス - List - 詳細

 クラウディア
1. 概要
2. 先頭・末尾
3. インデックス
4. 要素のインデックスを取得
5. コピー

1. 概要

 ここから、少し細かい話にはいっていきます。  本ページは、下記のサイトを参考にさせていただきました。
C# List(リスト)のコピー」
「[C#]List(リスト)の要素のインデックスを取得するには?

2. 先頭・末尾

 リストの先頭と末尾を取得するには、「[]」で囲んで、インデックスを指定するやり方もありますが・・・。  上記の例でいうと

myClass first = list[0];
myClass last  = list[list.Count-1];
 明示的に「First」「Last」というメソッドを使用する方法もあります。  前項のソースの 24~38 行を下記のように編集して

		list.Sort((a, b) => a.i - b.i);

		myClass first = list.First();
		myClass last  = list.Last();

        Console.WriteLine(@"first ["+ first.i +@"] ["+ first.s +@"]");
        Console.WriteLine(@"last  ["+ last.i +@"] ["+ last.s +@"]");
 実行すると、下記の結果が得られます。

first [1] [Z]
last  [3] [X]

3. インデックス

 わたしは、めったに使わないのですが、「FindIndex」というメソッドで、「List」内のインデックスを求めることができます。  前項の例でいうと

		List<myClass> list01 = new List<myClass>
			{
				new myClass { age = 20, name = @"hogehoge" },
				new myClass { age = 20, name = @"fugafuga" },
				new myClass { age = 21, name = @"piyopiyo" },
			};

        Console.WriteLine(@"hogehoge index = [" + list01.FindIndex(x => String.Equals(x.name, "hogehoge")) + @"]");
        Console.WriteLine(@"piyopiyo index = [" + list01.FindIndex(x => String.Equals(x.name, "piyopiyo")) + @"]");
        Console.WriteLine(@"pemopemo index = [" + list01.FindIndex(x => String.Equals(x.name, "pemopemo")) + @"]");
 を実行すると

hogehoge index = [0]
piyopiyo index = [2]
pemopemo index = [-1]
 という結果が得られます。  これで、インデックスは、「0」始まりであること、条件に合致するものがないときは、「-1」が返ってくることがわかります。

4. 要素のインデックスを取得

 抽出した要素のインデックスを

public int IndexOf (T item);
 で取得することができます。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

public class MyMain
{
	[Serializable]
	public class myClass
	{
		public int		i	= 0;												// 数値型要素
		public string	s	= String.Empty;										// 文字列型要素
	}

	static public void Main ()
	{
		List<myClass> list = new List<myClass>
			{
				new myClass { i = 2, s = "Y" },
				new myClass { i = 1, s = "Z" },
				new myClass { i = 3, s = "X" },
				new myClass { i = 5, s = "Y" },
				new myClass { i = 2, s = "X" },
				new myClass { i = 2, s = "Z" },
			};

		myClass myClass = list.Find(x => (x.i == 5) && string.Equals(x.s, "Y"));

        Console.WriteLine("i["+ myClass.i +"] s["+ myClass.s +"] のインデックス["+ list.IndexOf(myClass) +"]");
	}
}
 てな、ソースを書き、ロードモジュールを作成して、実行すると、下記の結果が得られます。

i[5] s[Y] のインデックス[3]

5. コピー

 参考サイトとか、あちこちに書いてあるのが、参照渡しと、値渡しの違いで。  「=」で、代入してしまうと、参照が渡ってしまうので、代入した先で変更したものが、代入元に反映される。  なので、値渡しするのであれば、「new」で、代入元を引数で渡すという話で。

using System;
using System.IO;
using System.Collections.Generic;

public class HelloWorld
{
	static public void Main ()
	{
		List<string> list01 = new List<string> { "hogehoge", "fugafuga", "piyopiyo" };

		List<string> list02 = list01;
		List<string> list03 = new List<string>(list01);

		list02[1] = @"ふがふが";

		foreach (string m in list01)
		{
	        Console.WriteLine(@"[" + m + @"]");
		}

        Console.WriteLine();

		list03[1] = @"へげへげ";

		foreach (string m in list01)
		{
	        Console.WriteLine(@"[" + m + @"]");
		}
	}
}
 上記のソースでロードモジュールを作成して、実行すると下記の結果が得られます。

[hogehoge]
[ふがふが]
[piyopiyo]

[hogehoge]
[ふがふが]
[piyopiyo]
 11行と12行の違いですな、前者は代入先を変更した結果が、代入元に反映され、後者は代入元には反映されないちゅうことです。  しかしこれ、よく考えると、「List」の中身がスカラ変数である場合のみの話です。

using System;
using System.IO;
using System.Collections.Generic;

public class myClass
{
	public int 	  age  = 0;
	public string name = String.Empty;
}

public class HelloWorld
{
	static public void Main ()
	{
		List<myClass> list01 = new List<myClass>
			{
				new myClass { age = 20, name = "hogehoge" },
				new myClass { age = 21, name = "fugafuga" },
				new myClass { age = 22, name = "piyopiyo" },
			};


		List<myClass> list03 = new List<myClass>(list01);

		list03[1].name = "ふがふが";

		foreach (myClass m in list01)
		{
	        Console.WriteLine("age = [" + m.age + "] name[" + m.name + "]");
		}
	}
}
 上記のソースでロードモジュールを作成して、実行すると下記の結果が得られます。

age = [20] name[hogehoge]
age = [21] name[ふがふが]
age = [22] name[piyopiyo]
 これ、驚くにはあたらないわけで。  23行目で、「List」としては、値渡しをしているのですが、「List」の中身は参照になっているので、中身を変えれば中身は変わっちゃうわけです。  「List」としては、値渡しになっているのは、上記の実行文の後に、下記の行を加えるとわかります。

		list03.Sort((a, b) => a.age - b.age);

        Console.WriteLine();

		foreach (myClass m in list01)
		{
	        Console.WriteLine("age = [" + m.age + "] name[" + m.name + "]");
		}

        Console.WriteLine();

		foreach (myClass m in list03)
		{
	        Console.WriteLine("age = [" + m.age + "] name[" + m.name + "]");
		}
 追加したものでロードモジュールを作成して、実行すると下記の結果が得られます。

age = [22] name[hogehoge]
age = [21] name[ふがふが]
age = [20] name[piyopiyo]

age = [22] name[hogehoge]
age = [21] name[ふがふが]
age = [20] name[piyopiyo]

age = [20] name[piyopiyo]
age = [21] name[ふがふが]
age = [22] name[hogehoge]
 「List」としては、別物になっているので、「Sort」の結果が、代入元には、及んでいないわけです。
earthcar(アースカー)
U-NEXT
ハイスピードプラン