今回のエンジニアブログを担当する加賀です。
C#のList
今回のコードはVS2010Pro SP1、C# 4.0で確認しています。
List
bool Remove( T item )
サンプルとして以下のプログラムを使用して動きを見てみます。
using System; using System.Collections.Generic; //Listの要素クラス public class Data { public int ID; public string Name; public int HP; public Data(int ID, string Name, int HP) { this.ID = ID; this.Name = Name; this.HP = HP; } public Data(int ID) { this.ID = ID; this.Name = ""; this.HP = 0; } } public class Example { static List<Data> DataList = new List<Data>(); //DataListの中身を表示 public static void ShowDataList() { Console.Out.WriteLine("ID Name HP"); foreach(Data data in DataList) { Console.Out.WriteLine(String.Format("{0,-4} {1,-8} {2}",data.ID,data.Name,data.HP)); } Console.Out.WriteLine(); } public static void Main() { DataList.Add(new Data(0, "Data1", 10)); DataList.Add(new Data(1, "Data2", 20)); Console.Out.WriteLine("List削除テスト"); ShowDataList(); //削除 Console.Out.WriteLine("ID 0を削除します\n"); DataList.Remove(new Data(0, "Data1", 10)); //削除後結果表示 ShowDataList(); Console.In.ReadLine(); } }
これは、デフォルトの比較はインスタンスが同じかどうかで比較をしているからです。
リストに登録した時のインスタンスと、Remove時に渡したインスタンスが別になるので、たとえ値がすべて同じだとしても一致してくれません。
◆解決法
今回の解決法は、DataクラスにIEquatable
今回は、IDが一致すればオブジェクト一致ということにしてあります。この辺りは自分で好きな様に書くことができます。
ただし、IEquatable
bool Equals( Object obj ) int GetHashCode()
今回修正する部分はDataクラスのみなので、解決後のコードはDataクラスのみ記述しておきます。
public class Data : IEquatable<Data> { public int ID; public string Name; public int HP; public Data(int ID, string Name, int HP) { this.ID = ID; this.Name = Name; this.HP = HP; } public Data(int ID) { this.ID = ID; this.Name = ""; this.HP = 0; } //IEquatable<Data>のEqualsメソッド public bool Equals(Data obj) { return (this.ID == obj.ID); } //オーバーライドしておくべき public override bool Equals(Object obj) { if (obj == null) return base.Equals(obj); if (obj is Data) return Equals(obj as Data); return false; } public override int GetHashCode() { return ID.GetHashCode(); } }
今回のように、IDという1つの値で識別するような場合はDictionaryを使えば簡単に実装できますが、2つ以上の値で識別したい場合などでも使えると思います。