iT邦幫忙

2022 iThome 鐵人賽

DAY 27
0

昨天原本想要寫利用rx傳遞事件狀態來寫個接收摩斯密碼的小程式,但發現我對IObservable物件的生命週期掌握不好導致結果難以預期就只好放棄了…..。今天蜻蜓點水一下延遲執行讓我有時間來準備明天介紹平行化,沒什麼重點還請見諒

IQueryable/IEnumerable

在.net中這兩個界面都具有linq擴充方法,差別在於底層的行為,IEnumerable是利用迭代器窮舉進行查詢,而IQuerable則是利用內部的IQueryProvider將查詢轉譯成指定的查詢方式,這裡就不贅述。

// 以Entity Framework來說

// _dbContext.Member的型別是IQueryable<Member>,套用where篩選後還不會得到結果
// _memberList的型別仍是IQueryable<Member>
var _memberList = this._dbContext.Member.Where(x => x.Age > 20);

// 使用ToList()才會真的取得資料
var memberList = _memberList.ToList();

Linq的延遲查詢特性對大家來說應該都不陌生。

無窮級數

有了延遲執行,就能夠將無窮的概念引入。在OO的設計中所有的資料都要在記憶體中分配實際的空間儲存,這一點先天限制了資料的大小。利用延遲執行的技術,我們可以將無窮的概念想像成本來就存在但尚未載入程式中的結果,當需要執行時,就可以將無窮收斂到當下需要的數值。在C#中要實現無窮的概念可以使用迴圈

IEnumerabel<int> InfiniteSequence()
{
		while(true) yield return 1;
}

使用yield return 語法糖在處裡無窮級數的時候真的非常方便。

Lazy

C#中還有一個型別叫做Lazy,可以延遲物件初始化,通常可以用在單例模式,同時它是執行緒安全的(Lazy是安全的,但裡面的值不是),Lazy的使用也具有monad的特性!

public static class LazyExtension
{
    public static Lazy<TResult> SelectMany<TSource, TSelector, TResult>
    (this Lazy<TSource> source, 
        Func<TSource, Lazy<TSelector>> selector,
        Func<TSource, TSelector, TResult> resultSelector) => 
        new Lazy<TResult>(() => resultSelector(source.Value, selector(source.Value).Value));

    public static Lazy<TResult> Select<T, TResult>(
        this Lazy<T> source,
        Func<T, TResult> selector)
        => new Lazy<TResult>(() => selector(source.Value));
}

這也代表了Lazy具有豐富的可組合特性

小結

今天又水過了一章,還剩下三天就完結了!


上一篇
Day26. Rx(4)
下一篇
Day28. Concurrency
系列文
Functional Programming with C#30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言