當通過一個動作可能是有用的,它並不像枚舉在樹結構中的所有項目的迭代器一樣靈活,使他們可用於其他LINQ運營商:
public static class ExtensionMethods
{
// Enumerate all descendants of the argument,
// but not the argument itself:
public static IEnumerable<T> Traverse<T>(this T item,
Func<T, IEnumerable<T>> selector)
{
return Traverse<T>(selector(item), selector);
}
// Enumerate each item in the argument and all descendants:
public static IEnumerable<T> Traverse<T>(this IEnumerable<T> items,
Func<T, IEnumerable<T>> selector)
{
if(items != null)
{
foreach(T item in items)
{
yield return item;
foreach(T child in Traverse<T>(selector(item), selector))
yield return child;
}
}
}
}
// Example using System.Windows.Forms.TreeNode:
TreeNode root = myTreeView.Nodes[0];
foreach(string text in root.Traverse(n => n.Nodes).Select(n => n.Text))
Console.WriteLine(text);
// Sometimes we also need to enumerate parent nodes
//
// This method enumerates the items in any "implied"
// sequence, where each item can be used to deduce the
// next item in the sequence (items must be class types
// and the selector returns null to signal the end of
// the sequence):
public static IEnumerable<T> Walk<T>(this T start, Func<T, T> selector)
where T: class
{
return Walk<T>(start, true, selector)
}
// if withStart is true, the start argument is the
// first enumerated item in the sequence, otherwise
// the start argument item is not enumerated:
public static IEnumerable<T> Walk<T>(this T start,
bool withStart,
Func<T, T> selector)
where T: class
{
if(start == null)
throw new ArgumentNullException("start");
if(selector == null)
throw new ArgumentNullException("selector");
T item = withStart ? start : selector(start);
while(item != null)
{
yield return item;
item = selector(item);
}
}
// Example: Generate a "breadcrumb bar"-style string
// showing the path to the currently selected TreeNode
// e.g., "Parent > Child > Grandchild":
TreeNode node = myTreeView.SelectedNode;
var text = node.Walk(n => n.Parent).Select(n => n.Text);
string breadcrumbText = string.Join(" > ", text.Reverse());
是的,這就是我做了什麼。我嘗試爲每個IEnumerable構建一個擴展(Enumerable)。但我的問題是/是擴展中的孩子(employee.Employees.Traverse)循環。 我首先想到的,我可以創建一個擴展,我可以從調用(如lambda或其他)調用「employee.employee」調用。 –
Khh
2010-07-19 13:48:00
@ k-hoffman:我編輯了我的答案以顯示該方法。 – 2010-07-19 13:51:34
是的,很有意思。大。非常感謝 – Khh 2010-07-19 17:55:55