趣旨
C#でファーストコレクションクラスを作成する際に、インスタンス変数に対象クラスのListを保持することが多かったが、もっとスマートな方法がないかと思い調査したので記録する。
oita.oika.me
要諦
- ファーストコレクションクラスでCollection
を継承する - ファーストコレクションクラスをフィルターすることがあるが、その方法についてまとめる
何がいいか
- 金融系SIでは約定データのListを操作することが多く、そのようなデータを扱う際にファーストコレクションを利用すると保守性向上に寄与すると感じる。
- また、Collection
を継承することで、これがファーストコレクションに相当するという実装意図が明確になり、ほかの人が見てもわかるソースになる。
ソース
説明
- usingは省略してます。
- 以下はMyClassという個別のクラスをまとめたファーストコレクションクラスを生成します。
- 生成後、index=1のデータのみフィルターします。その際、List
型ではなく、ファーストコレクションクラス自身を返します。
クライアント側
class Program { static void Main(string[] args) { var myCollction = new MyClassCollection(); //△ List<MyClass>型:List操作になるため、MyClassCollectionを作成した意味が半減する //また外部からデータを操作するのは望ましくない var val1 = myCollction.Where(x => x.index == 1).ToList(); //〇 MyClassCollection型:想定通り var val2 = myCollction.ToFliter(); } }
ファーストコレクションクラス
internal class MyClassCollection : Collection<MyClass> { public MyClassCollection() { //1,2,3の値を保持するデータを生成 var xxx = new MyClass(1); var xxx2 = new MyClass(1); var xxx3 = new MyClass(1); var xxx4 = new MyClass(1); var xxx5 = new MyClass(2); var xxx6 = new MyClass(3); base.Items.Add(xxx); base.Items.Add(xxx2); base.Items.Add(xxx3); base.Items.Add(xxx4); base.Items.Add(xxx5); base.Items.Add(xxx6); } //★こいつでフィルターした結果を生成可能 private MyClassCollection(IList<MyClass> list) : base(list) { } public MyClassCollection ToFliter() { var list = base.Items.Where(x => x.index == 1).ToList(); return new MyClassCollection(list); //★引数付コンストラクタ } }
個別のクラス
internal class MyClass { public int index { get; private set; } public MyClass(int i) { this.index = i; } }
参考 Collectionの中身
namespace System.Collections.ObjectModel { [DefaultMember("Item")] public class Collection<T> : ICollection<T>, IEnumerable<T>, IEnumerable, IList<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection, IList { public Collection(); public Collection(IList<T> list); public T this[int index] { get; set; } public int Count { get; } protected IList<T> Items { get; } public void Add(T item); public void Clear(); public bool Contains(T item); public void CopyTo(T[] array, int index); public IEnumerator<T> GetEnumerator(); public int IndexOf(T item); public void Insert(int index, T item); public bool Remove(T item); public void RemoveAt(int index); protected virtual void ClearItems(); protected virtual void InsertItem(int index, T item); protected virtual void RemoveItem(int index); protected virtual void SetItem(int index, T item); } }