要開始寫部落格了 取得連結 Facebook Twitter Pinterest 以電子郵件傳送 其他應用程式 5月 25, 2017 看了那麼多年的部落格,得到很多知識,非常佩服。 終於我也要開始耕耘這塊地方,希望大家來拜訪時,先看一下我的簡介,有幫助。 那麼,就開始吧~ 取得連結 Facebook Twitter Pinterest 以電子郵件傳送 其他應用程式 留言
揭開 C#.NET 官方原始碼 System.Func、System.Action、System.Delegate 及 delegate 關鍵字背後的技術面紗 10月 08, 2019 當 我們談到 delegate 和 lambda、Func、Action 這幾個字眼時,腦中觀念上總是有些模糊不清,就像是遠方有一片烏雲,雖然遙遠,卻擔心有一天會飄過來。我認為基本觀念很重要,像是delegate/Delegate大小寫代表不同意思,全小寫的delegate是C#關鍵字,Delegate/MulticastDelegate是函式庫類別,Func和Action是BCL預先定義方法簽章的17組委派類型,這34組方法簽章都是泛型函式。另外,官方有些文件存在著一些描述上令人困惑的文字,甚至我聽到有「Func和Action就是繼承自Delegate類別的衍生類別」的奇怪說法在流傳著,基於存在著這些奇點現象,若我們真的想要知道上述觀念是否正確時,最好的方法是直接看原始碼才能見分曉。 本文試著透過官方.NET基礎類別函式庫(BCL)的原始程式碼(Source Code)一窺堂奧,解釋編譯器怎麼編譯一個delegate語法或者怎麼實作,並提出個人見解以饗諸公。 探索System.Func、System.Action、System.Delegate原始碼 二話不說先給兩個官方Source Code網址: System.Func/System.Action: https://referencesource.microsoft.com/#mscorlib/system/action.cs System.Delegate: https://referencesource.microsoft.com/#mscorlib/system/delegate.cs,0dd8585ba1833ad7 坦白說我看不到10秒就看出「 貓膩 」了, 本文寫下心得,也可以說是依據個人有限知識+腦補的結果,但目的是期望能拋磚引玉,看到更多討論C#語法的觀念文,去幫助新手建立正確的程式根基。 先離題一下,談談這篇文章的濫觴, 隨著科技進步,現在的程式設計師跟以前寫程式的人的相比,有著很大的不同。 早期的程式設計師撰寫低階或中階語言,仰賴自身對計算機各種運算單元和IO知識,也要對資料結構的演算方法有足夠的學習,程式實體只有程式人員寫的語法和電腦機器碼兩種。 現代的程式設計師進行程式寫作是否能有高品質的程式碼產出,端依賴對該語言的關鍵字和類別 繼續閱讀
從Lambda語法來探討.NET LINQ的技術底蘊到底在哪裡? 10月 02, 2019 語言整合查詢 LINQ(Language Integrated Query) 世界最高的山叫聖母峰(珠穆朗瑪峰),而讓主脈看起來偉大神聖的,就是環繞的支線山脈稜線風光,群山烘托出一幅一幅壯絕的美景。.NET的LINQ就像聖母峰主山脈一樣,匯集各項技術才完成整個技術的淬鍊,成就偉業。(此時腦中浮現美隊大喊:Avengers! assemble...) 就在Python、C++、C#、PHP以及Javascript這些語言都支援Lambda語法的當今,還不會寫Lambda的程式人員請考慮移民火星,因為地球越來越危險了。 然後我們不免好奇一件事,究竟Lambda( 發音 )的由來和原理是甚麼,我們只知道使用Lambda可以少寫很多代碼,它可以用來寫匿名函式給Delegate委派、寫Linq必用、能把函式當參數傳、可以inline寫一長串程式碼超爽der...等等神奇又便利的特性,生在現代的程式設計師是不是太幸福了呢? ... 但也許我們就像瞎子摸象故事中那些盲(忙)人一樣,天天盲(忙)著工作,成本和速度儼然主宰了一切,漸漸對技術駕馭無能為力,直到彼此都在用荒謬溝通。 網路上大多是介紹Lambda語法的文章,完整精闢的觀念文缺乏,發現越來越多彼此對Lambda有一些認知上的差距;隨著.NET 的版本不斷演進,C#這個語言已進入一個全新的里程碑,而時下最夯的程式技術詞彙:Lambda 則是引爆一切的原點,究竟Lambda成就了C#,還是LINQ成就了這一切,卻把光環都給了Lambda,就讓我試著來整理這些資料,幫大家系統性的做一個介紹。 從Lambda起源說起 Lambda原本是一套數學邏輯表達式 : λ演算, 我們先來看維基上的介紹: 「λ演算(英語:lambda calculus,λ-calculus)是一套從數學邏輯中發展,以變數綁定和替換的規則,來研究 函式 如何抽象化定義、函式如何被應用以及 遞迴 的 形式系統 。它由數學家 阿隆佐·邱奇 在20世紀30年代首次發表。lambda演算作為一種廣泛用途的計算模型,可以清晰地定義什麼是一個可計算函式,而任何可計算函式都能以這種形式表達和求值,它能類比單一磁帶 圖靈機 的計算過程;儘管如此,lambda演算強調的是變換規則的運用,而非實現它們的具體機器。 「lamb 繼續閱讀
C# 物件屬性的建構賦值與初始化 - C# constructor and object initializer 9月 28, 2019 寫這篇是起因於在臉書討論C# DTO時我講了"建構賦值比物件初始化優先"這句話(其實我的意思是指先執行),不明白的人請我解釋是甚麼意思,所以就完整交代一下個人設計DTO物件的心得。 當然,若設計其他非DTO物件會更複雜一些... DTO不宜設計成一個複雜的邏輯物件,一般來說我們設計DTO物件時主要是做關於[屬性]的驗證和存取層級的規格設定。 另外,屬性的驗證應止於型別與範圍的安全,所以我們用屬性的get和set方法就可以達到這個需求。 設計每個DTO首先都要面臨3個課題,如下: 1.參考型別的屬性建構時是否實例化。 2.屬性型別與範圍的安全驗證。 3.屬性值的存取保護。 DTO要做到上述課題的完美解答,設計者除了要對物件導向的精神有足夠的認知與內化,還需要正確掌握C#語言的執行方式。這裡提供兩個觀念和技巧﹔ 1.要清楚DTO實例化的過程(C#建構函式與初始化程式碼區塊{}的執行順序) 有幾個重點: 1.屬於參考型別的屬性(例如List<T>)若沒有先實例化就沒辦法使用其API。 2.物件初始化語法區塊中無法執行類似 "new myClass{ myList[0] = "my string", ...}" 這樣編譯器會報錯,因為參考型別的實例化必須等到物件本身完成實例化之後,所以物件初始化要賦值屬性時不能參考到其資料結構,就算程式碼已宣告其值都要等到初始化後才能使用。類似以下例子: 2.更進階的觀念:讓關鍵屬性私有化並限制只能於建構時期賦值 由於物件建構階段比物件初始化階段先完成,所以相同屬性若在建構賦值之後會又被初始化覆蓋。 為了保護建構值我們可以在屬性private set中設計驗證程式碼,然後在建構函式傳入值到setter時驗證後才設定其值。這樣建構函式本身簡潔乾淨,屬性值又不會被初始化覆蓋或後續從外部修改。類似以下例子: 寫在最後 也許目前為止看似一切都妥當,但若是遇到非DTO而是較複雜的物件設計,程式常常會由不同程式人員維護,可能會在程式某處重複設定屬性myList的值,而我們本意是只能在建構時以參數設定myList。 有沒有方法保護程式碼呢? 答案是肯定的。 作法是把負責建構關鍵組態的程式設計 繼續閱讀
留言
張貼留言