《[深入淺出 C#] (第3版)》 - 學習筆記

来源:https://www.cnblogs.com/GATTACA2011/archive/2020/03/31/12607470.html

《深入淺出 C#》 (第3版) [作者] (美) Andrew Stellman (美) Jennifer Greene[譯者] (中) 徐陽 丁小峰 等譯[出版] 中國電力出版社[版次] 2016年08月 第1版[印次] 2018年04月 第4次 印刷[定價] 148.00元 【引子】 要學習編程 ...


《深入淺出 C#》 (第3版)

========== ========== ==========
[作者] (美) Andrew Stellman (美) Jennifer Greene
[譯者] (中) 徐陽 丁小峰 等譯
[出版] 中國電力出版社
[版次] 2016年08月 第1版
[印次] 2018年04月 第4次 印刷
[定價] 148.00元
========== ========== ==========

【引子】

要學習編程,沒有別的辦法,只能通過編寫大量代碼。

編寫代碼是一種技巧,要想在這方面擅長,只能通過實踐。

【第01章】

(P007)

IDE 的優點在於,它能自動地為你生成一些代碼,但是它的作用僅此而已。

不過,對於編程中最困難的部分,也就是確定你的程式要做什麼以及如何讓它能真正做到, IDE 就無能為力了。

IDE 為你做的所有一切,包括它創建的每一行代碼,增加的每一個文件,都是可以修改的,你可以直接手動地編輯文件,也可以通過 IDE 簡便易用的界面來修改。

【第02章】

(P054)

IDE 是一個功能強大的工具,不過僅此而已,這隻是一個可供使用的工具。

(P056)

可以認為 IDE 是一種方便的文件編輯器。它會自動為你完成縮進,改變關鍵字的顏色,完成括弧匹配,甚至還能建議下一個可能的詞是什麼。不過,歸根結底,IDE 所做的只是編輯文件,這些文件包含了你的程式。

(P057)

Windows Runtime 和 .NET Framework 中的工具劃分為不同的命名空間 (namespace) 。

Windows 8 中的每個程式都在一個稱為 Windows Runtime (Windows 運行時) 的體繫結構上運行。不過在 Windows Runtime 與你的程式之間還有另外的一 “層” ,這稱為通用語言運行時庫 (Common Language Runtime , CLR) 。

(P060)

每個 C# 程式的代碼結構幾乎完全一樣。所有程式都使用了命名空間、類和方法,使代碼更易於管理。

每次建立一個新程式時,要為它定義一個命名空間,使程式代碼與 .NET Framework 類和 Windows Store API 類區別開。

類包含程式的一部分。

類中有一個或多個方法。方法總是放在類中。

方法由語句組成。

類文件中方法的順序並不重要。

(P065)

只有使用了 partial 關鍵字時才能將一個類劃分到不同文件中。

(P066)

C# 使用變數類型來限制變數能存儲哪些數據。

(P067)

要想確保不會忘記對變數賦值,最容易的方法是把聲明變數的語句與為變數賦值的語句結合起來。

(P076)

可以使用 && 操作符或 || 操作符把單個條件測試結合為一個長測試, && 表示與 (AND) , || 表示或 (OR) 。

(P093)

每個 C# 都必須有一個名為 Main 的方法。這個方法就是代碼的入口點。

運行代碼時, Main() 方法中的代碼最先執行。

【第03章】

(P108)

對象 (Object) 是 C# 的一個工具,可以用來處理一組類似的事物。

(P109)

類對於對象來說就像是設計藍圖。

一旦構建一個類,可以根據需要使用 new 語句創建多個對象。創建對象後,類中的各個方法都將成為對象的一部分。

(P111)

從一個類創建新對象時,這稱為創建這個類的一個實例。

(P115)

靜態方法不要求有實例,而非靜態方法需要先有一個實例。

(P116)

方法是對象做什麼,欄位是對象知道什麼。

對象的行為由方法定義,另外使用欄位來跟蹤它的狀態。

(P118)

程式創建一個新對象時,會把它增加到堆中。

(P122)

類圖是一種將類畫在紙上的簡單方法。這是一個很有意義的工具,利用類圖,可以在編寫代碼之前設計代碼。

(P133)

對象初始化方法可以節省你的時間,使代碼更緊湊,更可讀 ······ 而且 IDE 會幫助你編寫對象初始化方法。

【第04章】

(P141)

實際上,編程中所做的幾乎每一件事都是在以這樣或那樣的方式處理數據。

(P142)

sbyte 中的 “s” 代表 “有符號” (signed) ,表示它可以是一個負數 (“符號” 就是一個負號) 。

“u” 代表 “無符號” (unsigned) 。

(P143)

在 C# 代碼中轉義序列寫為兩個字元,不過程式會把各個轉義序列作為單個字元存儲在記憶體中。

(P144)

所有數據都會占據記憶體中的一定空間。

利用變數,可以在記憶體中預留足夠的空間來存儲數據。

(P147)

將一個數值賦至 float 時,需要在這個數字後面加一個 “F” ,告訴編譯器這是一個 float 而不是 double 。否則,代碼將不能編譯。

(P148)

使用 “+” 將一個字元串與另一種類型的某個值或變數連接時,它會自動地將數字轉換為字元串。

(P149)

形參 (parameter) 是方法中定義的參數。實參 (argument) 是向方法傳入的參數。

(P158)

要讓一個對象留在堆中,它必須被引用。對象的最後一個引用消失一段時間後,對象也會消失。

(P170)

對象使用 this 關鍵字時,就是指自己,這個引用指向調用 this 的對象。

(P171)

創建一個新引用但是還沒有為它設置任何對象時,它也會有一個值。剛開始時會設置為 null ,這說明它不指向任何對象。

如果一個對象有一個引用,而且以後不再使用這個對象,將它的引用設置為 null 時,就會立即將這個對象標誌為可以回收 (除非別處還有這個對象的一個引用) 。

(P172)

要使用對象中的方法和欄位,唯一的途徑就是通過引用。

變數之所以稱為變數,就是因為它們總在改變。

在一個實例化對象的代碼中,實例可以使用這個特殊的 this 變數,其中包含它自己的一個引用。

【第05章】

(P211)

充分考慮到你的懶惰 —— 如果沒有加上 “private” 或 “public” 聲明, C# 就會認為這個欄位是私有的。

(P214)

一個對象要得到另一個對象私有欄位中存儲的數據,只有一個辦法 : 就是使用能返回該數據的公共欄位和方法。

寫一個類時,一定要保證為其他對象提供了一個途徑來得到它們需要的數據。私有欄位是封裝的一個很重要的部分,但是它們並不是全部。要編寫一個封裝性好的類,意味著要為其他對象提供一個合理的、易於使用的途徑來得到它們需要的數據,但不允許它們非法截獲你的類本身依賴的數據。

一個對象要得到另一個不同類型對象的私有欄位中存儲的數據,唯一的途徑就是使用返回該數據的公共方法。

(P217)

封裝是指讓一個類對另一個類隱藏信息。這有助於避免程式中的 bug 。

(P219)

如果你今天能很好地封裝類,明天重用這些類會容易得多。

(P221)

如果沒有合適的理由,就不要將欄位或方法聲明為公共。如果程式中的所有欄位都聲明為公共欄位,可能會把問題搞得一團糟。不過也不要把一切都設置為私有。先花一些時間來考慮這個問題,哪些欄位確實需要公共的,而哪些不必,以後這會為你節省很多時間。

(P226)

對象初始化方法中只能初始化公共欄位和屬性。

(P227)

要向類增加一個構造函數,只需要增加一個與類同名的方法,而且沒有返回值。

(P229)

方法中能做的,在屬性中也都可以做。

屬性 (獲取和設置存取方法) 是一種特殊類型的 C# 方法,只有當讀寫屬性時才會運行。

(P231)

如果在變數前增加 this 關鍵字,就是在告訴編譯器你所指的是欄位,而不是參數。

(P234)

封裝可以使你的類以後更易於理解和重用。

【第06章】

(P241)

對於只有一行代碼的代碼塊,大括弧是可選的。

(P260)

使用 override 關鍵字向子類增加一個方法,可以替換它繼承的方法。覆蓋一個方法之前,需要在基類中將這個方法標誌為 virtual 。

(P265)

任何方法需要一個類作為參數時,完全可以輸入擴展這個類的一個子類的實例。

(P268)

如果子類只是增加一個與超類方法同名的方法,那麼它只是隱藏了超類方法而不是覆蓋這個方法。

(P271)

如果你想覆蓋一個基類中的方法,一定要用 virtual 關鍵字標誌這個方法,如果希望在子類中覆蓋這個方法,就要使用 override 關鍵字。如果沒有做到這一點,很可能會無意中隱藏方法。

(P272)

即使子類覆蓋了基類中的方法或屬性,有時仍可能希望訪問基類中的這個成員。幸運的是,可以使用 base 關鍵字,利用這個關鍵字就可以訪問基類中的任何方法。

【第07章】

(P296)

使用介面要求一個類包含介面中所列的全部方法和屬性。如果類沒有做到這一點,編譯器會報錯。

只要編譯代碼時類中有介面要求的方法和屬性,介面並不關心這些方法或屬性是如何得來的。

(P297)

介面不存儲數據,所以不能增加任何欄位。

公共介面中的所有方法都會自動成為公共方法,因為介面就是用來定義實現該介面的類的公共方法和屬性。

(P298)

介面的目的是讓一個類可以完成多個任務,而不依賴於繼承,因為繼承會帶來很多額外的負擔,你必須繼承每一個方法、屬性和欄位,而不只是與處理特定任務有關的那些成員。

(P300)

在介面中不需要輸入 “public” 因為會自動將介面中的各個屬性和方法置為公共。

(P303)

跟蹤對象時,介面引用與對象引用同樣有效。

可能並不需要一個對象引用,完全可以創建一個新對象,並把它直接賦給一個介面引用變數。

(P304)

利用 “is” 可以比較介面,也可以比較其他類型。

(P305)

由於所有介面中都沒有具體的方法體,所以不需要考慮調用基類構造函數或方法。繼承介面 (子介面) 只需彙集它繼承的介面的所有方法和屬性。

(P306)

任何類可以實現任何介面,只要它能信守承諾,實現該介面的所有方法和屬性。

(P307)

“is” 指出一個對象實現了什麼, “as” 則告訴編譯器如何看待一個對象。

(P309)

向上強制轉換唯一的缺點是,只能使用基類的屬性和方法。

一旦將一個子類向上強制轉換為基類,由於訪問對象使用的是基類引用,所以只能訪問這個基類的方法和屬性。

(P310)

向下強制轉換的第一步是使用 “is” 關鍵字檢查有沒有這種可能。

(P312)

如果向下強制轉換是非法的, as 語句只會返回 null 。

介面中不允許有任何語句。

介面就像一個清單,編譯器檢查這個清單來確保類實現了指定的方法。

(P315)

我們把一個類的方法、欄位和屬性稱為它的成員 (members) 。所有成員都可以標誌 public 或 private 訪問修飾符。

將一個類成員標誌為 private 時,只有這個類中的成員或該類的其他實例能訪問這個成員。

不能把一個類標誌為 private ,除非這個類位於另一個類內部,在這種情況下,它只對它的 “容器” 類的實例可用。

類成員預設為私有,如果希望它是公共的,需要明確標識為公共。

聲明一個類成員時如果沒有訪問修飾符,就預設為 private 。

protected 對於子類表示 public ,對其他表示 private 。

子類不能訪問其基類中的私有欄位,另外必須使用 base 關鍵字才能訪問基類對象的公共成員。

標誌 protected 的類成員可以由該類中所有其他成員訪問,另外該類子類中的所有成員也可以訪問。

聲明一個類或介面時,如果沒有訪問修飾符,預設設置為 internal 。

如果你沒有使用多個程式集, internal 對於類和介面來說就相當於 public 。

(P318)

利用屬性,可以讓一個東西在其他對象看來像是一個欄位,但由於它實際上是一個方法,這樣就不會真正存儲任何數據。

介面引用只知道這個介面中定義的方法和屬性。

(P320)

抽象類可以有欄位和方法,而且也可以繼承其他類,這與正常類是一樣的。

抽象類可以包含屬性和方法的聲明,與介面一樣,子類必須實現這些屬性和方法。

抽象類和具體類之間最大的區別在於,不能使用 new 創建抽象類的實例。

如果一個方法有聲明但是沒有語句或方法體,這稱為一個抽象方法 (abstract method) 。就像繼承介面一樣,繼承抽象類的子類必須實現所有抽象方法。

只有抽象類可以有抽象方法。如果把一個抽象方法放在一個類中,就必須標誌這個類為抽象類,否則無法編譯。

(P322)

將一個類標誌為 abstract 時, C# 不允許你編寫代碼來實例化這個類。這很像介面,它就相當於一個模板,繼承它的子類都要以它為模板。

為類聲明增加 abstract 關鍵字,這就告訴 C# 這是一個抽象類,不能實例化。

(P323)

介面中的各個方法自動作為抽象方法,所以在介面中不需要像抽象類中那樣使用 abstract 關鍵字。

抽象類可以有抽象方法,不過也可以有具體方法。

(P330)

封裝是指創建一個對象,使用私有欄位在內部記錄它的狀態,另外通過公共屬性和方法使其他類只能使用它們需要看到的那部分內部數據。

(P331)

將一個類的實例用在需要其他類型 (如父類或這個類實現的介面) 的語句或方法中,這就是在使用多態。

【第08章】

(P353)

enum 數據類型只允許某個數據取某些特定的值。

大括弧里的內容稱為枚舉項列表 (enumerator list) ,其中每一項稱為枚舉項 (enumerator) 。整體稱為枚舉 (enumeration) 。

(P354)

可以把一個 int 強制轉換為一個 enum ,還可以把一個 (基於 int 的) enum 強制轉換回 int 。

(P358)

用數組來存儲一個固定的值或引用列表還不錯,但是如果需要移動數組元素,或者要增加超出數組容量的更多元素,就有些麻煩了。

(P363)

List 有一大特點 : 創建 List 時你不需要知道它會有多長。 List 會自動伸縮來適應它的內容。

foreach 迴圈也能處理數組,實際上, foreach 迴圈適用於任何集合。

(P367)

“泛型” (generic) 是指,儘管 List 的一個特定實例只能存儲一種特定類型,但 List 類適用於任何類型。

創建一個新的 List 對象時,總要提供一個類型,告訴 C# 它會存儲什麼類型的數據。

(P368)

集合初始化方法可以使代碼更緊湊,可以把創建列表和增加一組初始項結合在一起。

(P371)

要讓 List 的內置 Sort() 方法對某個類排序,只需讓這個類實現 IComparable<T> 介面,並增加一個 CompareTo() 方法。

List.Sort() 方法知道如何對實現了 IComparable<T> 介面的類或類型排序。這個介面只有一個成員,即 CompareTo() 方法。 Sort() 使用一個對象的 CompareTo() 方法與其他對象比較,並使用其返回值 (一個 int) 來確定哪一個在前。

但是有時需要對沒有實現 IComparable 介面的對象列表排序,對此, .NET 中的另一個介面可以提供幫助。可以向 Sort() 傳入一個實現了 IComparer<T> 的類的實例。這個介面也只有一個方法。List 的 Sort() 方法使用這個比較對象的 Compare() 方法來比較一對對象,從而得出它們在有序列表中的先後順序。

(P373)

要使用 IComparer<T> 排序時,需要創建實現這個介面的類的一個新實例。這個對象的存在是為了幫助 List.Sort() 確定如何對數組排序。

(P377)

每個 .NET 對象都有一個名為 ToString() 的方法,這個方法可以把對象轉換為一個字元串。預設地,它只是返回類名。

聯接字元串的 “+” 操作符會自動調用一個對象的 ToString() 。

Console.WriteLine() 或 String.Format() 也會在傳入對象時自動調用這個方法,如果你想把一個對象轉換為一個字元串,這會很方便。

(P379)

集合初始化方法適用於任何 IEnumerable<T> 對象,只要它有一個 Add() 方法。

集合實現 IEnumerable<T> 時,就為你提供了一種方法,可以編寫迴圈按順序迴圈處理其中的內容。

(P380)

如果你想把一個對象集合增加到一個更通用的列表中,協變就非常有用。

List.AddRange() 方法,這個方法可以把一個列表的內容增加到另一個列表中。

(P401)

隊列是先入先出型 (first-in first-out) ,這說明入隊列的第一個對象也就是最先取出使用的對象。

棧是先進後出型 (first-in last-out) ,最先進入棧的對象將最後一個取出。

可以使用 foreach 迴圈處理棧或隊列,因為它們都實現了 IEnumerable 。

【第09章】

(P410)

流 (stream) 是 .NET Framework 為程式提供的讀寫數據的方法。

如果希望對文件讀寫數據,就會使用一個 Stream 對象。

(P411)

流允許讀寫數據。要針對所處理的數據使用適當類型的流。

(P412)

FileStream 一次只能關聯一個文件。

流向文件寫位元組,所以需要將要寫的 string 轉換為一個 byte 數組。

關閉文件,使其他程式能夠訪問這個文件。

如果忘記關閉流,這是一個嚴重的問題。如果沒有關閉流,文件會被鎖定,其他程式在你關閉這個流之前將無法使用這個文件。

(P413)

StreamWriter 會為你自動創建和管理一個 FileStream 對象。

可以向 StreamWriter() 構造函數傳入一個文件名。如果傳入了文件名,書寫器 (writer) 會自動打開這個文件。 StreamWriter 還有一個重載構造函數,允許你指定它的追加模式 : 傳入 true 表示要把數據增加 (或追加) 到一個現有文件的末尾,傳入 false 會告訴流要刪除現有文件,再創建一個同名的新文件。

如果保持流打開並關聯到一個文件,就會鎖定這個文件一直處於打開狀態,其他程式將無法使用這個文件。所以一定要關閉文件。

(P417)

StreamReader (繼承自 TextReader) 是一個從流讀取字元的類。它本身不是一個流。將一個文件名傳入這個類的構造函數時,它會為你創建一個流,調用它的 Close() 方法時它會關閉這個流。

StreamReader 還有一個重載的構造函數,有一個 Stream 參數。

EndOfStream 屬性指出文件中是否還有未讀的數據。

(P418)

可以把流串起來,一個流可以寫到另一個流,而這個流又可以再寫到下一個流······ 最後通常是網路或者一個文件流。

(P424)

File 類完成少量操作時速度更快,而 FileInfo 更適合完成大量任務。

(P425)

StreamReader 和 StreamWriter 會為你將位元組轉換為字元,這稱為編碼和解碼。

如果只是按部就班地向一個文本文件讀寫文本行,那麼只需要 StreamReader 和 StreamWriter 就足夠了。

(P429)

在一個 using 塊中聲明一個對象,這個對象的 Dispose() 方法會自動調用。

對於任何實現了 IDisposable 介面的類,只要調用了它的 Dispose() 方法,會給立即釋放它占用的資源。通常這是結束對象處理的最後一步。

(P430)

每個流都有一個 Dispose() 方法,它會關閉這個流。所以如果在一個 using 語句中聲明流,它總會自行關閉。

所有流都實現了 IDisposable ,所以只要使用流,都應當在一個 using 語句中聲明。這樣能確保流總是會關閉。

可以在 using 語句上再羅列其他 using 語句,不需要另外的大括弧或縮進。

(P437)

switch 語句將一個變數與多個可能值進行比較。

每個 case 都必須以 “break;” 結束,這樣 C# 才能知道一種情況在哪裡結束,下一個在從哪裡開始。

還可以用 “return” 結束一個 case ,只要一個 case 不會繼續 “落入” 下一個 case ,程式就能編譯。

switch 語句的體是一系列 case 語句,將 switch 關鍵字後面的變數與一個特定值比較。

每個 case 都包括一個 case 關鍵字,後面時要比較的值和一個冒號。然後是一系列語句,最後是 “break;” 。如果這個 case 中的值與比較值匹配,就會執行這些語句。

(P444)

將對象複製到文件或者從文件讀出一個對象很簡捷。可以完成串列化和逆串列化。

(P451)

使用 File.Create() 時,這會創建一個新文件,如果已經有這樣一個文件,這個方法會把原文件刪除而創建一個全新的文件。另外還有一個 File.OpenWrite() 方法,它會打開原來的文件,並從頭開始覆蓋。

【第10章】

(P498)

定義頁面控制項的 XAML 會成為一個 Page 對象,它的欄位和屬性包含這些 UI 控制項的運用。

(P512)

XAML 中的數據綁定是指源屬性與目標屬性之間的一種關係,源屬性是為控制項提供數據的對象 (數據對象) 的一個屬性,目標屬性是顯示該數據的控制項 (控制項對象) 的一個屬性。要建立數據綁定,控制項的數據上下文必須設置為這個數據對象的一個引用。必須將控制項的綁定 (binding) 設置為一個綁定路徑,就是要綁定到對象的這個屬性。一旦完成這些設置,控制項就會自動讀取源屬性,並作為控制項的內容顯示這個數據。

(P513)

.NET 提供了 ObservableCollection<T> ,這是一個專門為數據綁定建立的集合類。

創建 XAML 代碼實現數據綁定時,它會使用一個 Binding 對象的實例來建立綁定,這個對象把目標屬性的名字存儲為一個字元串。

(P525)

頁面中的靜態資源會在頁面首次載入時實例化,應用中的對象可以在任何時候使用這些靜態資源。

(P526)

可以讓數據對象通知它們的目標屬性和綁定控制項,告訴它們數據已經改變。你要做的就是實現 INotifyPropertyChanged 介面,這個介面中包含一個名為 PropertyChanged 的事件。只要一個屬性有變化,就會觸發這個事件,可以看到綁定控制項會自動自行更新。

(P527)

要通知一個綁定控制項某個屬性有變化,你要做的就是調用 OnPropertyChanged() ,並提供發生變化的那個屬性的名字。

【第11章】

(P544)

可以使用一個新技術重新構建你之前已經構建的一個程式,這是掌握這種新技術的一個非常好的方法。

方法中有一個 await 時,在這個方法的聲明中必須有一個 async 。

(P546)

使用二進位串列化時,你寫的是 “純” 數據 : 會把記憶體中的實際位元組連起來,寫到一個文件中,另外會為二進位格式化工具提供足夠的信息,使它能確定哪些位元組對應對象圖中的哪些類成員。

(P547)

數據契約 (data contract) 是與類關聯的一個正式約定。這個契約使用 [DataContract] 和 [DataMember] 屬性來定義串列化時要讀寫什麼數據。

如果你想串列化一個類的實例,可以為它建立一個數據契約,在最上面增加 [DataContract] 屬性,然後為要串列化的各個類成員增加 [DataMember] 屬性。

(P557)

要讓一個 async 方法調用另一個非同步方法,被調用的方法的返回類型必須是 Task 類 (或者,如果這個方法需要返回一個值,返回類型也可以是它的子類 Task<T>) 。

推薦的命名約定是在使用 await 操作符調用的非同步方法名末尾增加 Async 。

async 修飾符、 await 關鍵字以及 Task 類都是為了更容易地編寫非同步代碼。

【第12章】

(P585)

把可能拋出異常的代碼放在 try 塊中。如果沒有發生異常,它會正常地運行, catch 塊中的語句將被忽略。不過,如果 try 塊中的某個語句確實拋出了一個異常, try 塊中的其餘語句就不會再執行。

(P587)

Watch 視窗中完成的所有修改只會影響記憶體中的數據,而且只持續到程式運行結束。重啟程式時,在 Watch 視窗中修改的值又會還原。

(P588)

把斷點加在 try 塊的開始大括弧上。

(P595)

在 catch 塊中指定一個異常類型時,如果提供了一個變數名,代碼就可以使用這個變數名來訪問這個 Exception 對象。

(P601)

要記住,在 “using” 語句中聲明一個引用時,會在這個塊末尾自動調用它的 Dispose() 方法。

使用 using 語句時,就是在充分利用 finally 來確保總會調用它的 Dispose() 方法。

(P602)

IDisposable 是避免常見異常和問題的一個非常有效的方法。處理實現了這個介面的類時,一定要使用 using 語句。

只有當一個類實現了 IDisposable 時,才能在 “using” 語句中使用這個類;否則,程式將不能編譯。

如果想在 using 語句中使用你的對象,它必須實現 IDisposable 。

IDisposable 介面只有一個成員 : Dispose() 方法。這個方法中的所有代碼都會在 using 語句的最後執行 ······ 或者手動調用 Dispose() 時執行。

實現 Dispose 的一個原則是你的 Dispose() 方法可以調用多次而沒有任何副作用。

(P604)

要記住,如果你的代碼沒有處理一個異常,這個異常會在調用棧中向上傳遞。讓異常向上傳遞是一種完全合法的異常處理方法,有時這比使用一個 try / catch 塊來處理異常可能更合適。

(P606)

只要使用流就應當使用 using 塊! 切記,切記,切記!

【第13章】

(P618)

最終化方法不能有參數,因為只需要告訴 .NET “搞定!” 就行了,除此之外不需要再說其他的。

(P619)

對象的最終化方法在所有引用都消失之後運行,而且是在對象被垃圾回收之前。對象的所有引用都消失時才會發生垃圾回收。不過,並不是引用一消失就進行垃圾回收。

如果不是一個 “玩具” 性的程式,就不要使用 GC.Collect() ,這是一個很糟糕的做法,這一點再強調也不為過,因為這會幹擾 CLR 的垃圾回收器。但這個方法非常適合用來學習垃圾回收和最終化方法。

(P627)

struct 可以實現介面,不過不能派生其他類,另外 struct 是密封的,所以不能派生 struct 。

struct 不是對象,它們可以有方法和欄位,但是不能有最終化方法。 struct 不能繼承其他類或 struct ,也不能被其他的類或 struct 繼承。

(P630)

設置一個 struct 等於另一個 struct 時,就是在為該 struct 中的數據創建一個全新的副本。這是因為 struct 是一個值類型。

(P634)

通過使用 out 參數,方法可以返回多個值。

每次調用一個有 out 參數的方法時,傳入實參時都要使用 out 關鍵字。

(P636)

如果希望方法有預設值,可以使用可選參數和命名參數。

(P637)

只需要在值類型後面增加一個問號 (?) ,它就會變成一個可為空的類型,可以將它設置為 null 。

每個可為空的類型都有一個名為 Value 的屬性,可以獲取或設置這個值。

它們還有一個名為 HasValue 的屬性,如果值不為 null 就會返回 true 。

值類型都可以轉換為一個可為空的類型。

不過要把可為空的類型再賦給一個值類型,則需要進行強制轉換。

如果 HasValue 為 false , Value 屬性會拋出一個 InvalidOperationException 異常,強制類型轉換也同樣會拋出這個異常 (因為強制轉換等價於使用 Value 屬性) 。

(P640)

如果希望為類提供很好的封裝, struct 會很有意義,因為返回一個 struct 的只讀屬性會建立它的一個全新副本。

(P642)

擴展方法總是靜態方法,而且必須放在靜態類中。

(P644)

定義擴展方法的類必須是一個靜態類。

(P648)

記住, as 關鍵字只用於類,不能用於 struct 。

【第14章】

(P653)

使用 LINQ 調用的方法實際上就是用來擴展數組的一些擴展方法。

(P667)

Take() 從 LINQ 查詢的第一個結果集中取出指定數目的數據項。可以把這些數據項放在另一個 var 中,然後再把它轉換到一個列表中。

利用 LINQ ,可以編寫查詢使用很少的代碼完成非常複雜的工作。

(P670)

from 子句會完成兩個工作 : 它告訴 LINQ 查詢使用哪個集合,另外為要查詢的集合中的各個成員指定一個名字。

select 子句告訴 LINQ 這個序列中應該有什麼。

(P679)

每個組包含一個共同的成員,稱為“組鍵”。使用 “by” 關鍵字來指定組鍵。每個組序列有一個 Key 成員,其中包含這個組的組鍵。

【第15章】

(P702)

你希望對象只考慮它自己,而不考慮其他對象。這裡就分離了各個對象的關註點。

(P704)

一個事件有一個發佈者,而且可以有多個訂購者。

(P705)

事件採用先來先服務的原則進行處理,最先訂購的對象最先得到通知。

(P706)

event 關鍵字後面是 EventHandler 。它不是 C# 的保留字,這是 .NET 中定義的一個關鍵字。之所以需要這個關鍵字,是為了告訴訂購這個事件的對象 : 它們的事件處理方法應該是什麼樣子。

使用 EventHandler 時,就是在告訴其他對象它們的事件處理方法應當有兩個參數,一個是名為 sender 的 object ,另一個參數是一個 EventArgs 引用,名為 e 。 sender 是產生事件的那個對象的引用, e 是 EventArgs 對象的一個引用。

(P709)

EventHandler 的作用就是定義事件的簽名,它告訴訂購這個事件的對象該如何定義事件處理方法。

一個事件總由一個對象產生。但是一個事件可以由多個對象響應。

(P716)

EventHandler 的泛型參數必須是 EventArgs 的一個子類。

(P731)

創建一個委托時,只需要為這個委托指向的方法指定方法簽名。

為工程增加一個委托時,就是在增加一個委托類型 (delegate type) 。用它創建一個欄位或變數時,就是在創建這個委托類型的一個實例。

(P732)

委托總是出現在所有其他類外面。

(P738)

回調是另一種使用委托的方式。

(P739)

向工程增加一個委托,就是在創建一個新類型,可以存儲方法的引用。

事件使用委托來通知對象有某些動作發生。

如果對象需要對某個對象中發生的事情做出反應,可以訂購這個對象的事件。

EventHandler 是一種委托,處理事件時這個委托很常用。

可以把多個事件處理方法串鏈到一個事件上。因此要用 “+=” 為事件設置事件處理方法。

在使用事件或委托之前,一定要檢查是否非 null ,以防止出現 NullReferenceException 異常。

一個對象將一個方法的引用傳入另一個對象,使它 (只有它) 能返回信息,這就稱為一個回調。

利用事件,任何方法都可以匿名地訂購對象的事件,而回調允許對象控制接收哪些委托。

回調和事件都使用委托來引用和調用其他對象中的方法。

(P740)

“回調” 只是使用委托 (或事件,完全可以使用一個私有事件來建立回調) 的一種方法。回調只是在兩個類之間建立一種關係,一個對象可以請求另一個對象的通知。相比之下,在事件中,則是一個對象要求得到事件通知。

【第16章】

(P749)

視圖模型就像是水管,利用一些工具 (你已經知道如何使用這些工具) 把視圖中的對象連接到模型中的對象。

(P764)

模型可以觸發一個事件,告訴應用的其餘部分某個重要的狀態發生了變化,而不需要引用模型以外的類。這樣更容易構建,因為它與其餘的 MVVM 層是解耦合的。

(P781)

MVVM 模式將視圖與視圖模型解耦合,另外將視圖模型與模型解耦合。

(P794)

把輔助方法放在一個靜態類中,而且類名以 “Helper” 結尾可以讓你的代碼更易讀。

(P795)

標誌為 readonly (只讀) 的欄位只能在聲明或構造函數中修改。


您的分享是我們最大的動力!

更多相關文章
  • title: Java基礎語法(7) 數組 blog: "CSDN" data: "Java學習路線及視頻" 1.數組的概述 數組(Array),是多個相同類型數據按一定順序排列的集合,並使用一個名字命名,並通過編號的方式對這些數據進行統一管理。 數組的常見概念 數組名 下標(或索引) 元素 數組的 ...
  • title: Java基礎語法(6) 註釋 blog: "CSDN" data: "Java學習路線及視頻" 用於註解說明解釋程式的文字就是註釋。 提高了代碼的閱讀性;調試程式的重要方法。 註釋是一個程式員必須要具有的良好編程習慣。 將自己的思想通過註釋先整理出來,再用代碼去體現 1.單行註釋 格式 ...
  • 一. 獲取多個單元格的值報錯:AttributeError: 'tuple' object has no attribute 'value' 需要讀取的sample.xlsx 代碼讀取的是A3:B10之間的單元格 運行結果: 二. 如何解決 上面報錯信息是,元組對象沒有屬性"value",我們先來看 ...
  • 原創聲明 本文作者:黃小斜 轉載請務必在文章開頭註明出處和作者。 什麼是消息隊列 “RabbitMQ?”“Kafka?”“RocketMQ?”...在日常學習與開發過程中,我們常常聽到消息隊列這個關鍵詞,可能你是熟練使用消息隊列的老手,又或者你是不懂消息隊列的新手,不論你了不瞭解消息隊列,本文都將帶 ...
  • 前言 為什麼要把反射和泛型放在一起講呢,這裡是處於個人對C 的一個很棒的觀感,因為C 的反射是可以獲取泛型里的元素的,而不像Java一個讓我比較難受的地方就是Java的泛型實際編譯的時候會擦除類型信息。 那麼問題來了,什麼是泛型,什麼又是反射呢? 泛型 請原諒我先介紹泛型,因為沒有泛型基礎直接介紹反 ...
  • 一種char分隔符 string phrase = "The quick brown fox jumps over the lazy dog."; string[] words = phrase.Split(' '); foreach (var word in words) { System.Con ...
  • 一、索引器(Indexer)允許類和結構的實例像數組一樣通過索引取值,可以看做是對[]運算符的重載,索引器實際上就是有參數的屬性,也被稱為有參屬性或索引化屬性,其聲明形式與屬性相似,不同之處在於索引器的訪問器需要傳入參數; 1.聲明索引器: class MyClass { string[] myAr ...
  • 記錄使用對象初始值設定項初始化對象。 using System; using System.Collections.Generic; namespace ConsoleApp2 { class Program { static void Main(string[] args) { // 使用構造函數 ...
一周排行
  • 文章篇幅較長,閱讀完大概20min,建議收藏閱讀, 讀完會有收穫。歡迎點贊關註 原文鏈接:https://www.softwaretestinghelp.com/types-of-software-testing/ 有多少軟體測試類型呢? 我們作為測試人員瞭解很多種不同的軟體測試類型,例如功能測試( ...
  • 過場CG: 接到公司領導的文件指示,“小熊”需要在6月底去海外執行一個行動代號為【定時任務】的營救計劃,這個計劃關係到公司某個項目的生死(數據安全漏洞),作戰部擬定兩個作戰方案: 方案一:使用務定時任務框架quartz; 方案二:使用windows Service服務。 最終的作戰方案為:兩者配套使 ...
  • 為什麼編寫TaskSchedulerEx類? 因為.NET預設線程池只有一個線程池,如果某個批量任務一直占著大量線程,甚至耗盡預設線程池,則會嚴重影響應用程式域中其它任務或批量任務的性能。 特點: 1、使用獨立線程池,線程池中線程分為核心線程和輔助線程,輔助線程會動態增加和釋放,且匯流排程數不大於參數 ...
  • 前幾天,公眾號後臺有朋友在問Core的中間件,所以專門抽時間整理了這樣一篇文章。 一、前言 中間件(Middleware)最初是一個機械上的概念,說的是兩個不同的運動結構中間的連接件。後來這個概念延伸到軟體行業,大家把應用操作系統和電腦硬體之間過渡的軟體或系統稱之為中間件,比方驅動程式,就是一個典型 ...
  • 參考文檔: https://www.cnblogs.com/liaods/p/10101513.html https://www.cnblogs.com/zyz-Notes/p/12030281.html 本示例使用MVC項目做演示(不推薦,推薦直接用WebAPI),框架版本使用 4.6.2 為了支 ...
  • 引用NModbus 在NuGet搜索NModbus,添加引用。 封裝ModbusTcp類 public class ModbusTCP { private ModbusFactory modbusFactory; private IModbusMaster master; private TcpCl ...
  • 系列文章 基於 abp vNext 和 .NET Core 開發博客項目 - 使用 abp cli 搭建項目 基於 abp vNext 和 .NET Core 開發博客項目 - 給項目瘦身,讓它跑起來 基於 abp vNext 和 .NET Core 開發博客項目 - 完善與美化,Swagger登場 ...
  • Microsoft.AspNetCore.Mvc.Versioning //引入程式集 .net core 下麵api的版本控製作用不需要多說,可以查閱https://www.cnblogs.com/dc20181010/p/11313738.html 普通的版本控制一般是通過鏈接、header此類 ...
  • 結合 AOP 輕鬆處理事件發佈處理日誌 Intro 前段時間,實現了 EventBus 以及 EventQueue 基於 Event 的事件處理,但是沒有做日誌(EventLog)相關的部分,原本想增加兩個介面, 處理事件發佈日誌和事件處理日誌,最近用了 AOP 的思想處理了 EntityFrame ...
  • 什麼是sam 轉換 Single Abstract Method 實際上這是java8中提出的概念,你就把他理解為是一個方法的介面的就可以了 看一下我們每天都在使用的線程池 ExecutorService executorService= Executors.newScheduledThreadPo ...