過了許久的時(shí)間,終于趁閑暇的時(shí)間來繼續(xù)將函數(shù)式編程這個(gè)專輯連載下去,這段時(shí)間開頭是為IOS這個(gè)新方向做準(zhǔn)備,將OC的教程寫成了SWIFT版,當(dāng)然我個(gè)人是支持Xamarin,但是我一般會(huì)先掌握原生態(tài)的開發(fā),再掌握Xamarin,
C#函數(shù)式編程之序列
。后面剩下的時(shí)間開發(fā)了一個(gè)Xamarin App項(xiàng)目,用了十幾天完成的。今天的內(nèi)容將對(duì)比較簡(jiǎn)單,就是講述如何利用函數(shù)式編程來實(shí)現(xiàn)列表推導(dǎo)。說的簡(jiǎn)單點(diǎn)就是列表的數(shù)據(jù)并不像我們平時(shí)開發(fā)那樣實(shí)現(xiàn)寫好的,而是通過一定的算法計(jì)算出來的(不是程序一打開就計(jì)算完成的,而是在使用的時(shí)候才計(jì)算的,并且只計(jì)算到我們使用的那一項(xiàng)為止)。用函數(shù)方法實(shí)現(xiàn)迭代器
首先我們當(dāng)然是先編寫一個(gè)高階函數(shù)來實(shí)現(xiàn)列表推導(dǎo)的主要功能部分,具體的代碼如下所示:
1 public static IEnumerable
2 {
3 if (getNext == null)
4 yield break;
5 yield return startVal;
6 T val = startVal;
7 while (endReached == null || !endReached(val))
8 {
9 val = getNext(val);
10 yield return val;
11 }
12 }
這個(gè)函數(shù)的作用就是根據(jù)一定的算法進(jìn)行迭代,而這里利用了C# 2.0才有的語法。該函數(shù)首先是根據(jù)startVal開始迭代,并且根據(jù)getNext計(jì)算下一個(gè)值,而endReached則用來約束結(jié)束條件。所以我們可以看到如果endReached為NULL也是可行的,這樣這個(gè)序列就是無窮的,當(dāng)然不是死循環(huán)。下面我們利用一段簡(jiǎn)單的代碼來掩飾如何使用這個(gè)函數(shù):
static void Main(string[] args)
{
var oddNumbersForm1 = Sequence
foreach (int x in oddNumbersForm1)
{
Console.WriteLine(x);
}
Console.ReadKey();
}
最后我們?cè)诿钚薪缑嬷锌梢钥吹饺缦碌娘@示:
值域
很多時(shí)候我們使用的序列都是很簡(jiǎn)單的,而利用上面的Sqquence函數(shù)則會(huì)變得復(fù)雜,同時(shí)這個(gè)函數(shù)還無法實(shí)現(xiàn)一些我們需要的功能,比如需要判斷一個(gè)值時(shí)候存在范圍中等等,所以我們下面將利用一個(gè)簡(jiǎn)單的Range來實(shí)現(xiàn)這些功能,當(dāng)然內(nèi)部還是使用的如上的Sequence函數(shù),下面是具體的代碼:
1 public class Range
2 {
3 private T start;
4 private T end;
5 private Comparison
6 private IEnumerable
7
8 private static int Compare(U one,U other)
9 {
10 return Comparer.Default.Compare(one,other);
11 }
12
13 public Range(T start, T end, Func
14 {
15 this.start = start;
16 this.end = end;
17 this.compare = compare;
18 this.sequence = Sequence
19 }
20
21 public Range(T start, T end, Func
22 : this(start, end, getNext, Compare) { }
23
24 public IEnumerator
25 {
26 return sequence.GetEnumerator();
27 }
28
29 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
30 {
31 return ((IEnumerable
32 }
33
34 public bool Contains(T value)
35 {
36 return compare(value, start) >= 0 && compare(end, value) >= 0;
37 }
38 }
通過上面的代碼我們可以看到Range的功能遠(yuǎn)遠(yuǎn)比Sequence函數(shù)要強(qiáng)大的多,并且我們可以看到我們還提供了Contains方法用來判斷指定的值是否在值域中,另外我們還可以獲得IEnumerable借口的各種擴(kuò)展方法供我們使用,
電腦資料
《C#函數(shù)式編程之序列》(http://www.ishadingyu.com)。限制
有時(shí)我們的迭代器的實(shí)現(xiàn)可能很復(fù)雜,如果還要加上限制不僅僅會(huì)影響到其性能,同時(shí)還會(huì)導(dǎo)致代碼的可讀性較差,所以我們可以將這兩者進(jìn)行分離,負(fù)責(zé)生成序列的函數(shù)只需要沒有任何限制,而將限制移轉(zhuǎn)到外部,比如函數(shù)TFunc是一個(gè)返回序列的函數(shù),并且沒有限制,而CFunc則接受一個(gè)最大值,以及用來計(jì)算序列的函數(shù),并且返回負(fù)責(zé)條件的序列,那么我們就可以像如下這樣循環(huán)獲取值:
1 foreach(int x in CFunc(10,TFunc)){
2 Console.WriteLine(x);
3 }
至此關(guān)于函數(shù)式編程中的序列就結(jié)束了,后面的時(shí)間筆者將會(huì)抓緊時(shí)間盡快將這個(gè)專輯結(jié)束掉,開始集中在Xamarin.Android這個(gè)系列的教程上。