2010-06-21 19 views
1

我的印象是,Func和Action的唯一區別是前者必須有返回值。所以我認爲你可以從Func或Action調用遞歸linq。我是C#的新手,我只是在試驗和好奇。使用LINQ和委託做遞歸函數

所以我嘗試以下遞歸打印類型內的嵌套類型。

Type t = typeof(Lev1); 
Action<Type> p1 = null, p2 = null; 
p1 = tn => 
    { 
     Console.WriteLine(tn.Name); 
     tn.GetNestedTypes().Select(x => { p1(x); return x; }); 
    }; 
p2 = tn => 
    { 
     Console.WriteLine(tn.Name); 
     tn.GetNestedTypes().ToList().ForEach(x => { p2(x);}); 
    }; 
p1(t); 
Console.WriteLine("=".PadRight(50, '=')); 
p2(t); 

所以我得到的結果是,P1(使用從Func鍵,即選擇遞歸)只打印頂層而P2它採用行動,即打印的foreach各級。

我以爲Func只是一個函數def,所以遞歸是有效的。當然我的理解是錯誤的有人可以解釋

+0

請不要在標題中重複標記(「C#LINQ」)。只要將它們留在標籤中即可。 – 2010-06-21 19:38:46

+4

如果我可以教人們關於查詢的一件事情,那就是:查詢表達式的結果(如您對Select的調用)是* query *。 *查詢*和*查詢*的結果是兩個完全不同的東西。查詢表達式的結果是* query *。如果你想要那個查詢的*結果*,你將不得不要詢問* execute *。現在請注意,編寫一個具有這種副作用的查詢是**最差的做法**。永遠不要這樣做。除了分配結果之外,執行查詢應該沒有副作用。 – 2010-06-22 02:51:58

+0

感謝埃裏克 - 我知道這是不是一個好的做法,寫選擇副作用.-我只是試驗,我不明白的結果 – josephj1989 2010-06-22 18:40:02

回答

4

您在第一次執行中只看到頂級的原因是因爲Selectlazilyevaluated。它僅在需要時纔開始返回值,例如,當您迭代它時(或者當您調用Sum或其他一些函數時)。如果在Select之後添加ToList()呼叫,它將起作用。

+0

它會工作:-) – 2010-06-21 19:41:49

1

您必須強制 IEnumerable - 這是懶! (它不一定總是,但要小心LINQ方法!)

在這種情況下,您放棄結果(和行動!)。好吧!

1

您需要將.ToList()添加到第一個Select()呼叫,因爲Linq功能是懶惰。在第二次調用中,遞歸因爲List<>.ForEach()(其名稱並不完全是foreach語句所做的)而起作用。