日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

c#扩展方法奇思妙用高级篇七:“树”通用遍历器

發布時間:2025/3/19 C# 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c#扩展方法奇思妙用高级篇七:“树”通用遍历器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我的上一篇隨筆《c#擴展方法奇思妙用高級篇六:WinForm 控件選擇器》中給出了一個WinForm的選擇器,其實質就是一個“樹”的遍歷器,但這個遍歷局限于WinForm的Control類。在數據結構中,“樹”的遍歷是一個通用算法,那我們為什么不做一個通用的“樹”遍歷擴展呢?

?

?先看一個簡單的類People(將作為測試用的例子):

1?????public?abstract?class?People
2?????{
3?????????public?bool?IsMale?{?get;?private?set;?}
4?????????public?abstract?IEnumerable<People>?Children?{?get;?}
5?????}

?People類有一個Children屬性,返回該People的所有孩子。People類通過Children屬性最終可形成一個People樹。

?“樹”的通用遍歷擴展一

參考代碼如下:

?1?????public?static?IEnumerable<T>?GetDescendants<T>(this?T?root,?
?2?????????Func<T,?IEnumerable<T>>?childSelector,?Predicate<T>?filter)
?3?????{
?4?????????foreach?(T?t?in?childSelector(root))
?5?????????{
?6?????????????if?(filter?==?null?||?filter(t))
?7?????????????????yield?return?t;
?8?????????????foreach?(T?child?in?GetDescendants((T)t,?childSelector,?filter))
?9?????????????????yield?return?child;
10?????????}
11?????}

調用示例?

使用People類,寫出幾個調用示例:

1?????People?people;
2?????//
3?????//獲取所有子孫
4?????var?descendants?=?people.GetDescendants(p?=>?p.Children,?null);
5?????//獲取所有男性子孫
6?????var?males?=?people.GetDescendants(p?=>?p.Children,?p?=>?p.IsMale);

?當然,還有另外一種情況,只獲取本族人的子孫(子孫中的女性嫁出,不包括她們的子孫),這種情況稍復雜些,本文更側重想法,不再給出示例代碼(哪們朋友實現了,可發在回復中)。

?既然是通用的,我們就將它用在WinForm中作為選擇器試試吧:

1?????//Form1.cs
2?????//獲取本窗體所有控件
3?????var?controls?=?(this?as?Control).GetDescendants(c?=>?c.Controls.Cast<Control>(),?null);
4?????//獲取所有選中的CheckBox
5?????var?checkBoxes?=?(this?as?Control).GetDescendants(
6?????????????c?=>?c.Controls.Cast<Control>(),
7?????????????c?=>?(c?is?CheckBox)?&&?(c?as?CheckBox).Checked
8?????????)
9?????????.Cast<CheckBox>();

?通用的方法寫起來肯定沒有專用的優雅,用了多處 is/as 和 Cast,主要因為這里涉及到繼承,而且Control.Controls屬性的類型ControlCollection不是泛型集合。

??“樹”的通用遍歷擴展二?

以上兩個例子比較相似:樹結構中“根”與“子孫”類型相同(或具有相同的基類),WinForm中的TreeView就不同了:TreeView(根)包含多個TreeNode(子孫),每個TreeNode也可包含多個TreeNode(子孫),“根”與“子孫”類型不同(也沒有相同的基類),如下圖:

?

?

?

源碼

我們要使用另外一個擴展(要調用上面的擴展方法):

?1?????public?static?IEnumerable<T>?GetDescendants<TRoot,?T>(this?TRoot?root,?
?2?????????Func<TRoot,?IEnumerable<T>>?rootChildSelector,??
?3?????????Func<T,?IEnumerable<T>>?childSelector,?Predicate<T>?filter)
?4?????{
?5?????????foreach?(T?t?in?rootChildSelector(root))
?6?????????{
?7?????????????if?(filter?==?null?||?filter(t))
?8?????????????????yield?return?t;
?9?????????????foreach?(T?child?in?GetDescendants(t,?childSelector,?filter))
10?????????????????yield?return?child;
11?????????}
12?????}

調用示例?

調用代碼如下:

1?????//獲取TreeView中所有以“酒”結尾的樹結點?????????????
2?????var?treeViewNode?=?treeView1.GetDescendants(
3?????????treeView?=>?treeView.Nodes.Cast<TreeNode>(),
4?????????treeNode?=>?treeNode.Nodes.Cast<TreeNode>(),
5?????????treeNode?=>?treeNode.Text.EndsWith("")
6?????????);

?

?有了這兩個擴展,相信能滿足大部分“樹”的遍歷,為了使用方便還可以進行一些重載。

?另外,“樹”的遍歷有 深度優先 和 廣度優先,這里只提一下,就不再一一給出示例了。

轉載于:https://www.cnblogs.com/ywsoftware/archive/2013/06/09/3128778.html

總結

以上是生活随笔為你收集整理的c#扩展方法奇思妙用高级篇七:“树”通用遍历器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。