IEnumerableインターフェイス継承クラスの自作
ListとIEnumerableの違い
{
var ary = Enumerable.Range(start: 1, count: 10);
var list = new List<int>();
list.AddRange(ary);
return list;
}
static IEnumerable<int> getList2()
{
var ary = Enumerable.Range(start: 1, count: 10);
var list = new List<int>();
list.AddRange(ary);
return list;
}
static IEnumerable<int> getList3()
{
foreach (var elm in Enumerable.Range(start: 1, count: 10))
{
yield return elm;
}
}
static void Main(string[] args)
{
var list1 = getList1();
List<int> = ~ と同じ
list1.ForEach(x => Console.WriteLine(x));
1 2 3 4 5 6 7 8 9 10
var list2 = getList2();
IEnumerable<int> = ~ と同じ
list2.ToList().ForEach(x => Console.WriteLine(x));
1 2 3 4 5 6 7 8 9 10
var list3 = getList3();
IEnumerable<int> = ~ と同じ
list3.ToList().ForEach(x => Console.WriteLine(x));
1 2 3 4 5 6 7 8 9 10
}
IEnumerable<T>型変数は「列挙オブジェクト」と呼ばれるクエリ式へのポインタ
それ自体はデータを持たず遅延実行されるのでメモリの節約になる。
容量を気にしなくて良い、複数回参照する場合は配列、リストの方が優れている
IEnumerable
foreach処理を可能にするインターフェイス
var i = Enumerable.Range(~).Where(~);
IEnumerable
List<int> myList = new List<int>() { 0,1,2,3,4,5 };
//foreach処理が可能
foreach(var i in myList)
{
Console.WriteLine(i);
//⇒ 0 1 2 3 4 5
}
↑ を自分で実装する。
using System.Collections;
public class MyCollection : IEnumerable
{
int[] _hoge;
public MyCollection()
{
_hoge = new int[] { 0,1,2,3,4 };
}
//IEnumerableインターフェイスの継承により、↓GetEnumerator()メソッドの実装が強制される
public IEnumerator GetEnumerator()
{
for (var i = 0; i < _hoge.Length; i++)
{
//yield:foreach処理で扱える形で返す
yield return _hoge[i];
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
MyCollection myCollection = new MyCollection();
//foreach処理が可能になっている。
foreach(var i in myCollection)
{
Console.WriteLine(i);
// ⇒ 0 1 2 3 4
}
}
Public Class MyCollection
Implements IEnumerable
Dim _hoge() As Integer
Public Sub New()
_hoge = { 0, 1, 2, 3, 4 }
End Sub
Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
‘ 配列をIEnumerable型へ変換
Dim enumerable As IEnumerable(Of Integer) = _hoge
Return enumerable.GetEnumerator
End Function
End Class
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim myCollection As New MyCollection()
For Each elm In myCollection
Console.WriteLine(elm)
’ ⇒ 0 1 2 3 4
Next elm
End Sub
IEnumerable<T>
・IEnumerableのジェネリック版(IEnumerableを継承している)
※「プログラム言語 ジェネリック」参照
・LINQの使用が可能
{
List<T> _hoge;
public MyCollection()
{
_hoge = new List<T>();
}
public void Add(T item)
{
_hoge.Add(item);
}
public IEnumerator<T> GetEnumerator()
{
for (var i = 0; i < _hoge.Count; i++ )
{
yield return _hoge[i];
}
}
// IEnumerableの継承による実装?
// Public修飾不可、IEnumerableの省略不可
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
public void Form1_Load(object sender, EventArgs e)
{
MyCollection<int> collection = new MyCollection<int>() { 0,1,2,3,4,5 };
// T : int としてインスタンスを作成。Add()を実行。
foreach (var i in collection)
{
Console.WriteLine(i);
// ⇒ 0 1 2 3 4 5
}
// IEnumerable<T>の場合、LINQが使用可能
List<int> myLINQ = collection.OrderByDescending(a => a).ToList();
foreach (var i in myLINQ)
{
Console.WriteLine(i);
// ⇒ 5 4 3 2 1 0
}
}