摘要:老趙提了個“僞”遞歸的說法
=========================
第一次列印出的120是正确的結果。不過facAlias從fac那裡“接過”了使用Lambda表達式構造的委托對象之後,我們讓fac引用指向了新的匿名方法x => x。于是facAlias在調用時:
自然就不對了。
=============================
老趙其實解釋得也很清楚:
這個Lambda表達式構造的“委托對象”在調用時,它會去尋找fac這個引用所指向的委托對象。請注意,這裡是根據“引用”去找“對象”,這意味着Lambda表達式構造的委托對象在調用時,fac可能已經不再指向當初的委托對象了。
我了解的意思就是老趙說facAlias的定義雖然看起來很像遞歸,但是本質上不是遞歸,是以一時興起起個名字叫“僞”遞歸
結果人家鶴沖天不幹了,覺得老趙對于Lambda遞歸有偏見。
==================================
public static Func<int, int> Fibonacci = n => n > 1 ? Fibonacci(n - 1) + Fibonacci(n - 2) : n;
是計算Fibonacci數列的,注意上這句代碼中用了“static”,可以編譯通過,絕對沒有問題!老趙回複中說不用static無法編譯通過,于是我又給出了以下代碼(以下稱為代碼二):
Func<int, int> Fibonacci = null;
Fibonacci = n => n > 1 ? Fibonacci(n - 1) + Fibonacci(n - 2) : n;
代碼二就是老趙随筆中開始處的那兩行被稱為“僞”遞歸代碼,所說的朋友自然就是我了!
===================================
呵呵,人家老趙沒說代碼二是僞遞歸呀。facAlies才是呢。并且老趙的希望不是僅僅構造一個遞歸,而是希望
我的想法是,既然使用“Lambda表達式來構造一個遞歸函數”的難點是因為“我們正在構造的東西是沒有名字的”,是以“我們無法調用自身”。那麼,如果我們換種寫法,把我們正在調用的匿名函數作為參數傳給自己,那麼不就可以在匿名函數的方法體中,通過調用參數來調用自身了嗎?
以及從這個出發點開始擴充下去的東西
這樣我們能清楚些,當我們執行委托的時候,會使用Invoke(args)來調用方法體,看清楚,是Invoke方法,并不是委托自己哦,這一點已經偏離了遞歸的概念了。
這是個原則性問題,我的跟帖也就是沖這個去的
其實很多問題根本不需要IL來湊熱鬧。
最後,使用最基礎的記憶體堆棧結構概念來解釋老趙的代碼
回顧基本概念,值類型、引用類型。
Func<int, int> fac = null;
fac = x => x <= 1 ? 1 : x * fac(x - 1);
Func<int, int> facAlias = fac;
fac = x => x;
Console.WriteLine(facAlias(5)); // 20
第一行,在記憶體中的情況如下
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL08lYtVHa09VZnFWbp9CX4gjR48FTJ9CXyVGdpJ3VlZXaMN3dvRmbpd1LcVHetU2cl5WaoN0Lc12bj91cn9Gbi52YvwVbvNmLzd2bsJmbj5ycldWYtl2Lc9CX6MHc0RHaiojIsJye.png)
第二行
第三行
第四行
第五行的運作結果自然就是老趙說的:
facAlias(5) <— facAlias是x => x <= 1 ? 1 : x * fac(x – 1)
= 5 <= 1 ? 1 : 5 * fac(5 - 1)
= 5 * fac(4) <— 注意此時fac是x => x
= 5 * 4
= 20
是以facAlias不是一個遞歸Lambda表達式,是以可以認為是一種“僞遞歸”
而
這裡的fac是一個如假包換的遞歸
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
最後謝謝各位觀賞
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接。
本文轉自徐少俠部落格園部落格,原文連結:http://www.cnblogs.com/Chinese-xu/archive/2009/09/02/1558547.html,如需轉載請自行聯系原作者