Memperbarui:
Untuk orang yang tertarik dengan level nesting (kedalaman). Salah satu hal baik tentang implementasi tumpukan enumerator eksplisit adalah bahwa setiap saat (dan khususnya saat menghasilkan elemen) stack.Countmewakili kedalaman pemrosesan saat ini. Jadi dengan mempertimbangkan hal ini dan memanfaatkan tupel nilai C # 7.0, kita cukup mengubah deklarasi metode sebagai berikut:
public static IEnumerable<(T Item, int Level)> ExpandWithLevel<T>(
this IEnumerable<T> source, Func<T, IEnumerable<T>> elementSelector)
dan yieldpernyataan:
yield return (item, stack.Count);
Kemudian kita dapat mengimplementasikan metode asli dengan menerapkan simple Selectdi atas:
public static IEnumerable<T> Expand<T>(
this IEnumerable<T> source, Func<T, IEnumerable<T>> elementSelector) =>
source.ExpandWithLevel(elementSelector).Select(e => e.Item);
Asli:
Anehnya tidak ada (bahkan Eric) yang menunjukkan port berulang "alami" dari DFT pra-order rekursif, jadi ini dia:
public static IEnumerable<T> Expand<T>(
this IEnumerable<T> source, Func<T, IEnumerable<T>> elementSelector)
{
var stack = new Stack<IEnumerator<T>>();
var e = source.GetEnumerator();
try
{
while (true)
{
while (e.MoveNext())
{
var item = e.Current;
yield return item;
var elements = elementSelector(item);
if (elements == null) continue;
stack.Push(e);
e = elements.GetEnumerator();
}
if (stack.Count == 0) break;
e.Dispose();
e = stack.Pop();
}
}
finally
{
e.Dispose();
while (stack.Count != 0) stack.Pop().Dispose();
}
}