《深入理解 C# (第2版)》 - 學習筆記

来源:https://www.cnblogs.com/GATTACA2011/archive/2020/03/04/12411394.html
-Advertisement-
Play Games

《深入理解 C#》 (第2版) [作者] (英) Jon Skeet[譯者] (中) 周靖 朱永光 姚琪琳[出版] 人民郵電出版社[版次] 2012年01月 第1版[印次] 2012年01月 第1次 印刷[定價] 79.00元 【關於本書】 具體地說, C# 作為一種語言,它的基礎是各種各樣的 “框 ...


《深入理解 C#》 (第2版)

========== ========== ==========
[作者] (英) Jon Skeet
[譯者] (中) 周靖 朱永光 姚琪琳
[出版] 人民郵電出版社
[版次] 2012年01月 第1版
[印次] 2012年01月 第1次 印刷
[定價] 79.00元
========== ========== ==========

【關於本書】

具體地說, C# 作為一種語言,它的基礎是各種各樣的 “框架庫” (.NET Framework 中的各種庫) 以及一個強大的運行時 (runtime) 。藉助它們,我們可以將抽象的東西轉變成現實。

【第01章】

(P013)

LINQ (Language Integrated Query , 語言集成查詢) ,是 C# 3 的核心之所在。顧名思義。 LINQ 是關於查詢的,其目的是使用一致的語法和特性,以一種易閱讀、可組合的方式,使對多數據源的查詢變得簡單。

(P014)

查詢表達式唯一的好處就是 where 子句顯得更簡單。

【第02章】

(P023)

實際上,委托在某種程度上提供了間接的方法。換言之,不需要直接指定一個行為,而是將這個行為用某種方式 “包含” 在一個對象中。

可以選擇將委托類型看做只定義了一個方法的介面,將委托的實例看做實現了那個介面的一個對象。

(P024)

為了讓委托做某事,必須滿足4個條件 :

1. 聲明委托類型;

2. 必須有一個方法包含了要執行的代碼;

3. 必須創建一個委托實例;

4. 必須調用 (invoke) 委托實例;

(P026)

如果有一個委托類型的變數,就可以把它視為方法本身。

(P028)

委托實例實際有一個操作列表與之關聯,這稱為委托實例的調用列表 (invocation list) 。

System.Delegate 類型的靜態方法 Combine 和 Remove 負責創建新的委托實例。其中, Combine 負責將兩個委托實例的調用列表連接到一起,而 Remove 負責從一個委托實例中刪除另一個的調用列表。

委托是不易變的,創建了一個委托實例後,有關它的一切就不能改變。這樣一來,就可以安全地傳遞委托實例,並把它們與其他委托實例合併,同時不必擔心一致性、線程安全性或者是否有其他人試圖更改它的操作。

(P029)

事件不是委托類型的欄位。

對於事件來說,必須是一個委托類型。

(P030)

對於一個純粹的事件,你所能做的事情就是訂閱 (添加一個事件處理程式) 或者取消訂閱 (刪除一個事件處理程式) 。

類內的代碼能看見欄位;類外的代碼只能看見事件。

(P037)

數組類型是引用類型,即使元素類型是值類型。

枚舉是值類型。

委托類型是引用類型。

介面類型是引用類型,但可由值類型實現。

(P039)

變數的值是在它聲明的位置存儲的。

只有局部變數 (方法內部聲明的變數) 和方法參數在棧上。

(P040)

當你調用類型變數值的 GetType() 方法時總是伴隨著裝箱過程,因為它不能被重載。

(P041)

引用類型作為方法參數使用時,參數預設是以 “值傳遞” 方式來傳遞的 —— 但值本身是一個引用。

【第03章】

(P047)

所謂 “函數化” 的編程風格,是指鼓勵開發者更多地利用委托。

(P048)

從根本上說,泛型實現了類型和方法的 “參數化” ,就像在普通的方法調用中,經常要用參數來告訴它們使用什麼值。

(P052)

類型參數是真實類型的占位符。

在泛型聲明中,類型參數要放在一對尖括弧內,並以逗號分隔。

使用泛型類型或方法時,要用真實的類型代替,這些真實的類型稱為類型實參 (type argument) 。

如果沒有為任何類型參數提供類型實參,聲明的就是一個未綁定泛型類型 (unbound generic type) 。如果指定了類型實參,該類型就稱為一個已構造類型 (constructed type) 。

我們知道,類型 (無論是否是泛型) 可以看做是對象的藍圖。同樣,未綁定泛型類型是已構造類型的藍圖。

在 C# 代碼中,唯一能看見未綁定泛型類型的地方 (除了作為聲明之外) 就是在 typeof 操作符內。

類型參數 “接收” 信息,類型實參 “提供” 信息,這個思路與 方法參數 / 方法實參 是一樣的。只不過類型實參必須為類型,而不能為任意的值。只有在編譯時才能知道類型實參的類型,它可以是 (或包含) 相關上下文中的類型參數。

(P054)

泛型類型可以重載,只需改變一下類型參數的數量就可以了。

(P057)

將 API 的一部分變成泛型後,以前強類型的方法調用就需要進行強制類型轉換。

(P062)

調用泛型方法時,指定類型實參常常會顯得很多餘。

類型推斷只適用於泛型方法,不適用於泛型類型。

(P063)

在 C# 語言規範中,只提供了數量有限的推斷步驟。

雖然很少需要用到預設值,但它偶爾還是有用的。

(P064)

輸出參數也稱為 out 參數,如果希望由方法本身初始化參數,允許向方法傳遞一個未初始化的實參,那麼在聲明參數時,就要附加 out 關鍵字作為首碼。

(P066)

共有 4 個主要的泛型介面可用於比較。 IComparer<T> 和 IComparable<T> 用於排序 (判斷某個值是小於、等於還是大於另一個值) ,而 IEqualityComparer<T> 和 IEquatable<T> 通過某種標準來比較兩個項的相等性,或查找某個項的散列 (通過與相等性概念匹配的方式) 。

如果換一種方式來劃分這 4 個介面, IComparer<T> 和 IEqualityComparer<T> 用於那些能夠比較兩個不同值的類型,而 IComparable<T> 和 IEquatable<T> 的實例則用於它們本身和其他值之間的比較。

(P073)

一個基本的原則是,如果沒有問題,泛型介面都應該繼承對應的非泛型介面,這樣可以實現協變性。

(P074)

實現介面所規定的的方法或屬性時,附加介面名作為首碼,即稱為 “顯式介面實現” 。

(P075)

反射的一切都是圍繞 “檢查對象及其類型” 展開的。

(P078)

泛型不支持協變性 —— 它們是不變體。

【第04章】

(P091)

Nullable<T> 最重要的部分就是它的屬性,即 HasValue 和 Value 。

(P092)

Nullable<T> 引入了一個名為 GetValueOrDefault 的新方法,它有兩個重載方法,兩者均在存在一個實例的前提下返回該實例的值,否則返回一個預設值。其中一個重載方法沒有任何參數 (在這種情況下會使用基礎類型的泛型預設值) ,另一個重載方法則允許你指定要返回的預設值。

【第05章】

(P114)

C# 2 支持從方法組到一個相容委托類型的隱式轉換。

(P117)

根據約定,事件處理方法應具有包含兩個參數的簽名。第 1 個參數是 object 類型,代表事件的來源;第 2 個參數則負責攜帶與事件有關的任何額外信息,該參數是從 EventArgs 派生的一個類型。

返回類型協變性和參數類型逆變性可以同時使用,雖然這樣做幾乎沒有任何實際的用處。

(P119)

.NET 2.0 引入了一個泛型委托類型 Action<T> ,我們將在例子中使用委托。它的簽名非常簡單 (除了它是泛型這一事實以外) : public delegate void Action<T>(T obj) 。

(P120)

匿名方法的語法 : 先是 delegate 關鍵字,再是參數 (如果有的話) ,隨後是一個代碼塊,其中包含了對委托實例的操作進行定義的代碼。

基本上,在普通方法主體中能做的事情,在匿名方法中都能做。同樣,匿名方法的結果是一個委托實例,可以像使用其他委托實例那樣使用它。

逆變性不適用於匿名方法,必須指定和委托類型完全匹配的參數類型。

(P121)

Action<T> 委托的返回類型是 void ,所以不必從匿名方法返回任何東西。

.NET 2.0 中的 Predicate<T> 委托類型,下麵列出了它的簽名 : public delegate bool Predicate<T>(T obj) 。

(P122)

謂語通常在需要篩選和匹配操作中使用。

Predicate<T> 類型聲明的返回類型恰好是 bool 。

(P124)

匿名方法是 C# 2 以被捕捉的變數的形式來實現,在別的地方成為閉包的一個特性。

(P125)

匿名方法能使用在聲明該匿名方法的方法內部定義的局部變數。

(P127)

簡單地說,捕獲變數能簡化編程,避免專門創建一些類來存儲一個委托需要處理的信息 (作為參數傳遞的信息除外) 。

FindAll 的參數是一個 Predicate<T> 委托。

【第06章】

(P138)

如果方法聲明的返回類型是非泛型介面,那麼迭代器塊的生成類型 (yield type) 是 object ,否則就是泛型介面的類型參數。

在迭代器中不允許包含普通的 return 語句 —— 只能是 yield return 。

(P141)

迭代器代碼塊不能實現具有 ref 或 out 參數的方法。

(P143)

只要調用者使用了 foreach 迴圈,迭代器塊中的 finally 將按照你期望的方式工作。

(P147)

迭代器方法中的 using 語句扮演了 try / finally 塊的角色。

(P148)

LINQ 的核心特性之一,是使用 Where 方法進行篩選。

【第07章】

(P154)

創建分部類型是非常容易做的事情 —— 你只需在涉及的每個文件的類型的聲明部分附加一個上下文關鍵字 partial 。

(P158)

分部方法的聲明方式與抽象方法相同 : 只使用 partial 修飾符提供簽名而無須任何實現。同樣,實際的實現還需要 partial 修飾符,不然就和普通方法一樣了。

由於方法可能不存在,分部方法必須具有 void 返回類型,不能獲取 out 參數。它們必須是私有的,不過可以是靜態的 並且 / 或是 泛型的。如果方法沒有在任何文件中實現,那麼整個調用語句就會被移除,包括任何參數的計算語句。

(P159)

實際上如果不存在可見的構造函數 (包括受保護的) ,那麼類實際上也就是密封的了。

(P160)

如果你不為類提供任何構造函數,那麼 C# 1 編譯器總是會提供一個公有的預設的無參數構造函數。

我們不希望出現任何可見的構造函數,所以不得不提供一個私有的。

C# 2 編譯器知道靜態類不用包含任何構造函數,所以它也不會提供預設的。實際上,編譯器在類定義上執行了大量的約束 :

1. 類不能聲明為 abstract 或 sealed ,雖然兩者都是隱含聲明的;

2. 類不能設定任何要實現的介面;

3. 類不能設定基類型;

4. 類不能包含任何非靜態成員,包括構造函數;

5. 類不能包含任何操作符;

6. 類不能包含任何 protected 或 protected internal 成員;

應當註意,即使所有成員都必須為靜態的,你還是要把它們都顯式地聲明為靜態的,除了嵌套類型和常量。雖然嵌套類型是外圍類的隱式靜態成員,不過如果不要求的話,嵌套類型本身可以不用是靜態的。

(P161)

讓類成為靜態的,就是在說你絕對不會創建該類的任何實例。

在 C# 1 中取值方法和賦值方法必須具有相同的可訪問性 —— 它作為屬性聲明的一部分進行聲明,而不是作為取值方法或賦值方法聲明的一部分進行聲明的。

(P162)

在 C# 的其他地方,在給定的情況下,預設的訪問修飾符可能大部分都是私有的。換句話說。如果某些內容能被聲明為私有,那麼省略的訪問修飾符就被完全預設為私有。這是一種很好的語言設計元素,因為這樣很難意外地發生錯誤 : 如果你希望某些內容更加公開,在你使用它的時候會註意到。

如果你不設定任何東西,那麼預設情況下 取值方法 / 賦值方法 和屬性本身整體上保持一致的訪問修飾符。

還要註意,你不能把屬性本身聲明為私有,而讓取值方法是公有的 —— 你只能設置比屬性更私有的特殊 取值方法 / 賦值方法 。

C# 1 的 using 指令能夠用於兩種情況 —— 一種是為命名空間和類型創建一個別名,另外一種就是將一個命名空間引入到當編譯器查找某個類型時可以搜索到的上下文列表中。

在 C# 2 中,有 3 種別名種類 : C# 1 的命名空間別名、全局命名空間別名和外部別名。

(P166)

對 pragma 指令進行描述通常都非常簡單 : pragma 指令就是一個由 #pragma 開頭的代碼行所表示的預處理指令,它後面能包含任何文本。

【第08章】

(P178)

不能在所有情況下為所有變數都使用隱式類型。只有在以下情況下才能用它 :

1. 被聲明的變數是一個局部變數,而不是靜態欄位和實例欄位;

2. 變數在聲明的同時被初始化;

3. 初始化表達式不是一個方法組,也不是一個匿名函數 (不進行強制類型轉換) ;

4. 初始化表達式不是 null ;

5. 語句中只聲明瞭一個變數;

6. 你希望變數擁有的類型是初始化表達式的編譯時類型;

7. 初始化表達式不包含正在聲明的變數;

(P184)

集合初始化列表並非只能應用於列表。任何實現了 IEnumerable 的類型,只要它為初始化列表中出現的每個元素都提供了一個恰當的公有的 Add 方法,就可以使用這個特性。

(P192)

如果你要創建的一個類型只在一個方法中使用,而且其中只包含了欄位和普通屬性,就考慮一下能否使用匿名類型。

(P193)

匿名類型允許你只保留特定情況下需要的數據,這些數據採取的是適用於那種情況的形式,不必每次都單調重覆地寫一個新的類型。

隱式類型的數組和匿名類型只有在與其他 C# 3 特性配合的時候才會體現它們的價值。

【第09章】

(P194)

LINQ 的基本功能就是創建操作管道,以及這些操作需要的任何狀態。這些操作表示了各種關於數據的邏輯 : 如何篩選、如何排序以及如何將不同的數據源聯接到一起,等等。當 LINQ 查詢在 “進程內” 執行時,那些操作通常用委托來表示。

LINQ to Objects 處理的是同一個進程中的數據序列。相比之下,像 LINQ to SQL 這樣的 provider 將工作交給 “進程外” 的系統 (比如資料庫) 去處理。

(P195)

執行委托只是 LINQ 的眾多能力之一。

從許多方面, Lambda 表達式都可以看做是 C# 2 的匿名方法的一種演變。

匿名方法能做的幾乎一切事情都可以用 Lambda 表達式來完成。

匿名方法可以簡明地忽略參數,但 Lambda 表達式不具備的這一特性。

在 .NET 3.5 的 System 命名空間中,有 5 個泛型 Func 委托類型。 Func 並無特別之處 —— 只是它提供了一些好用的預定義泛型類型,在很多情況下能幫助我們處理問題。每個委托簽名都獲取 0 ~ 4 個參數,參數類型是用類型參數來指定的。最後一個類型參數用作每種情況下的返回類型。

(P196)

當你想使用 void 為返回類型時,可使用 Action<...> 系列的委托,其功能相同。

Action 的單參數的版本在 .NET 2.0 中就有了,但其他都是 .NET 3.5 新增的。

如果 4 個參數還嫌不夠, .NET 4 將 Action<...> 和 Func<...> 家族擴展為擁有 16 個參數,因此 Func<T1, ..., T16, TResult> 擁有讓人欲哭無淚的 17 個類型參數。

Lambda 表達式最冗長的形式是 : { 顯式類型參數列表} => { 語句 } 。

=> 部分是 C# 3 新增的,它告訴編譯器我們正使用一個 Lambda 表達式。

(P197)

在閱讀 Lambda 表達式時,可以將 => 部分看成 “goes to” 。

匿名方法中控制返回語句的規則同樣適用於 Lambda 表達式 : 如果返回類型是 void ,就不能從 Lambda 表達式返回一個值;如果有一個非 void 的返回類型,那麼每個代碼路徑都必須返回一個相容的值。

對於沒有返回類型的委托,如果只有一條語句,也可以使用這種語法,基本上省略分號和大括弧。

表達式,不使用大括弧,不使用 return 語句,也不添加分號 : { 顯式類型的參數列表 } => 表達式 。

編譯器大多數時候都能猜出參數類型,不需要你顯式聲明它們。在這種情況下,可以將 Lambda 表達式寫成 : ( 隱式類型的參數列表 ) => 表達式 。

隱式類型的參數列表就是一個以逗號分隔的名稱列表,沒有類型。但隱式和顯式類型的參數不能混合和匹配 —— 要麼整個列表都是顯式類型的,要麼全部都是隱式類型的。除此之外,如果有任何 out 或 ref 參數,就只能使用顯式類型。

(P198)

如果 Lambda 表達式只需一個參數,而且那個參數可以隱式指定類型, C# 3 就允許省略圓括弧。這種格式的 Lambda 表達式是 : 參數名 => 表達式 。

是否為 Lambda 表達式的主體使用較短的形式 (指定一個表達式來取代一個完整的代碼塊) ,以及是使用顯式還是隱式參數,這兩個決定是完全獨立的。

(P202)

.NET 3.5 的表達式樹提供了一種抽象的方式將一些代碼表示成一個對象樹。

C# 3 對於將 Lambda 表達式轉換成表達式樹提供了內建的支持。

(P205)

Lambda 表達式能顯式或隱式地轉換成恰當的委托實例。

並非所有 Lambda 表達式都能轉換成表達式樹。不能將帶有一個語句塊 (即使只有一個 return 語句) 的 Lambda 轉換成一個表達式樹 —— 只有對單個表達式進行求值的 Lambda 才可以。

(P208)

沒有 Lambda 表達式,表達式樹幾乎沒有任何價值。

從一定程度上說,反過來說也是成立的 : 沒有表達式樹, Lambda 表達式肯定就沒那麼有用了。

(P218)

匿名函數是匿名方法和 Lambda 表達式的統稱。

(P219)

Lambda 表達式要想被編譯器理解,所有參數的類型必須為已知。

在 C# 3 中, Lambda 表達式幾乎完全取代了匿名方法。當然,為了保持向後相容,匿名方法仍是支持的。

【第10章】

(P220)

C# 3 引入了擴展方法的概念,它既有靜態方法的優點,又使調用它們的代碼的可讀性得到了增強。使用擴展方法,可以像調用完全不同的類的實例方法那樣調用靜態方法。

(P223)

並不是任何方法都能作為擴展方法使用 —— 它必須具有以下特征 :

1. 它必須在一個非嵌套的、非泛型的靜態類中 (所以必須是一個靜態方法) ;

2. 它至少要有一個參數;

3. 第一個參數必須附加 this 關鍵字作為首碼;

4. 第一個參數不能有其他任何修飾符 (比如 out 或 ref) ;

5. 第一個參數的類型不能是指針類型;

(P226)

實例方法肯定會先於擴展方法使用。

在 C# 中,在空引用上調用實例方法是不允許的。

可以在空引用上調用擴展方法。

(P227)

在框架中,擴展方法最大的用途就是在 LINQ 中使用。

(P229)

Where 擴展方法是對集合進行篩選的一種簡單但又十分強大的方式 : 它接受一個謂詞,後者應用於原始集合中的每個元素。 Where 同樣返回一個 IEnumerable<T> ,但這一次所有與謂詞匹配的元素都被包括到結果集合中。

(P230)

“返回相同的引用” 模式用於易變類型,而 “返回新實例 (該實例為原始實例更改後的副本)” 模式則用於不易變類型。

(P233)

LINQ 操作符是無副作用的 : 它們不會影響輸入,也不會改變環境。

(P236)

C# 3 只支持擴展方法而不支持擴展屬性,這稍微限制了流暢介面。

(P239)

我們學東西不應過於急功近利 —— 每次都是為瞭解決當前的一個實際問題才去學習。

在軟體工程領域,新的模式和實踐準則層出不窮,來自一些系統的設計思想經常會 “流竄” 到另一些系統中。這其實是讓軟體開發始終保持新鮮感的原因之一。

【第11章】

(P241)

序列是 LINQ 的基礎。

(P251)

Cast 通過把每個元素都轉換為目標類型 (遇到不是正確類型的任何元素的時候,就會出錯) 來處理,而 OfType 首先進行一個測試,以跳過任何具有錯誤類型的元素。

(P254)

編譯器會故意生成一個對 Select 方法的調用,即使它什麼都沒有做。

查詢表達式的結果和源數據從來就不是同一個對象,除非 LINQ 提供器的代碼有問題。從數據集成的角度看,這是很重要的 —— 提供器能返回一個易變的結果對象,並知道即使面對一個退化查詢,對返回數據集的改變也不會影響到 “主” 數據。

(P255)

OrderBy 和 ThenBy 不同之處非常簡單 : OrderBy 假設它對排序規則起決定作用,而 ThenBy 可理解為對之前的一個或多個排序規則起輔助作用。

(P256)

儘管你能使用多個 orderby 子句,但每個都會以它自己的 OrderBy 或 OrderByDescending 子句作為開始,這意味著最後一個才會真正 “獲勝” 。

let 子句只不過引入了一個新的範圍變數,它的值是基於其他範圍變數。語法是極其簡單的 : let 標識符 = 表達式 。

(P258)

let 子句使用對 Select 的另一個調用,為結果序列創建匿名方法,並最終創建了一個新的範圍變數 (它的名稱在源代碼中從未看到或用到) 來實現目標。

(P260)

如果你打算把一個巨大的序列聯接到一個極小的序列上,應儘可能把小序列作為右邊序列。

(P261)

通常,你希望過濾序列,而在聯接前進行過濾比在聯接後過濾要有效得多。

內聯接可用在 SQL 的所有地方,它們實際上是從某個實體導航到相關聯的實體上的一種方式,通常是把某個表的外鍵和另外一個表的主鍵進行聯接。

(P264)

交叉聯接不在序列之間執行任何匹配操作 : 結果包含了每個可能的元素對。

(P268)

分組表達式通過分組鍵決定了序列如何分組。整個結果就是一個序列,序列中的每個元素本身就是投影後元素的序列,還具有一個 Key 屬性,這就是那個用於分組的鍵;這樣的組合是封裝在 IGrouping<TKey, TElement> 介面中的,它擴展了 IEnumerable<TElement> 。

(P270)

查詢延續提供一種方式,把一個查詢表達式的結果用作另外一個查詢表達式的初始序列。它可以應用於 group...by 和 select 子句上,語法對於兩者是一樣的 —— 你只需使用上下文關鍵字 into ,併為新的範圍變數提供一個名稱就可以了。範圍變數接著能用在查詢表達式的下一部分。

【第12章】

(P277)

LINQ to SQL 需要有關資料庫的元數據,來知道哪個類與哪個資料庫表相對應等信息。可以用幾種不同的方式來表示這種元數據,而我這裡使用的是 Visual Studio 內嵌的 LINQ to SQL 設計器。

【第13章】

(P312)

參數 (也稱為形式參數) 變數是方法或索引器聲明的一部分,而實參是調用方法或索引器時使用的表達式。

(P313)

如果某個操作需要多個值,而有些值在每次調用的時候又往往是相同的,這時通常可以使用可選參數。

(P314)

指定了預設值的參數為可選參數。

(P315)

可選參數包含一些規則。所有可選參數必須出現在必備參數之後,參數數組 (用 params 修飾符聲明) 除外,但它們必須出現在參數列表的最後,在它們之前為可選參數。參數數組不能聲明為可選的,如果調用者沒有指定值,將使用空數組代替。可選參數不能使用 ref 或 out 修飾符。

(P316)

基本上,你必須使用永遠不會改變的真正常量作為可選參數的預設值。

(P318)

如果要對包含 ref 或 out 的參數指定名稱,需要將 ref 或 out 修飾符放在名稱之後,實參之前。

(P319)

實參是按照參數的名稱來匹配的,而不再是參數的位置。

未命名的實參稱為位置實參。

所有命名實參都必須位於位置實參之後,兩者之間的位置不能改變。位置實參總是指向方法聲明中相應的參數 —— 你不能跳過參數之後,再通過命名相應位置的實參來指定。

(P331)

可變性有兩種類型 : 協變性和逆變性。

協變性用於向調用者返回某項操作的值。

逆變性則相反。它指的是調用者向 API 傳入的值,即 API 是在消費值,而不是產生值。

(P332)

在泛型介面或委托聲明中, C# 4 能夠使用 out 修飾符來指定類型參數的協變性,使用 in 修飾符來指定逆變性。

任何使用了協變和逆變的轉換都是引用轉換,這意味著轉換之後將返回相同的引用。它不會創建新的對象,只是認為現有引用與目標類型匹配。

如果類型參數只用於輸出,就使用 out ,如果只用於輸入,就用 in 。

(P337)

只有介面和委托可以擁有可變的類型參數。即使類中包含只用於輸入 (或只用於輸出) 的類型參數,仍然不能為它們指定 in 或 out 修飾符。

【第14章】

(P345)

事實上, dynamic 並不代表一個特定的 CLR 類型,它實際上只是包含 System.Dynamic.DynamicAttribute  特性的 System.Object 。

(P347)

dynamic 可用來聲明類型的欄位、參數和返回值。這與 var 形成了鮮明的對比,後者只能用於局部變數。

(P355)

如果兩個方法的簽名包含的參數類型相同,編譯器將選擇非泛型重載,而不是泛型重載。

(P362)

dynamic 類型的參數將被視為 object 類型 —— 如果查看編譯後的代碼,將發現它確實為 object 類型的參數,只不過應用了額外的特性。這還意味著在你聲明的方法中,它們的簽名不能只以 dynamic / object 參數類型來進行區分。

(P369)

你不能聲明一個基類為 dynamic 的類型,你同樣不能將 dynamic 用於類型參數的約束,或作為類型所實現的介面的一部分。你可以將其用於基類的類型實參,或在聲明變數時將其用於介面。


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

-Advertisement-
Play Games
更多相關文章
  • 1. Java和C++最大的不同在於Java採用的指針模型可以消除重寫記憶體和損壞數據的可能性。 2. Java沒有C++的多重繼承,取而代之的是更簡單的介面概念。 3. 從一開始Java就設計能防範各種攻擊,包括:運行時堆棧溢出、破壞自己的進程空間之外的記憶體、未經授權的讀寫文件。 4. javac程 ...
  • 獸人,金幣,布爾…… 看這麼多次都膩了。最起碼我們得把他們簡化一點。 簡介 使用 與 (AND) 操作符時,如果第一個條件 (在 AND 左邊那個) 為假,第二個條件 (右邊那個) 永遠不會執行。 你可以好好利用這點! 這些代碼有可能出錯: enemy = hero.findNearestEnemy ...
  • PhalApi是一款國人製作的PHP純後端框架。它的開發相當簡單,同時也具備文檔生成等特色功能。下麵,我通過簡單的幾點,讓你可以快速入門使用該框架的開發。 建議使用PHPStorm作為IDE,代碼提示相當完全。由於PHP的熱更新特性,修改過的PHP文件保存後立即生效,無需編譯,無需重啟伺服器。 什麼 ...
  • 什麼是Websocket 我們在傳統的客戶端程式要實現實時雙工通訊第一想到的技術就是socket通訊,但是在web體系是用不了socket通訊技術的,因為http被設計成無狀態,每次跟伺服器通訊完成後就會斷開連接。 在沒有websocket之前web系統如果要做雙工通訊往往使用http long p ...
  • 以上是代碼 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication ...
  • 讓 mac 本地和自己的 github 網站建立連接(ssh) 下載安裝 git 網址: https://git-scm.com/downloads 查看安裝是否成功: git -version $ git version git version 2.15.1 (Apple Git-101) che ...
  • 帶著問題去思考,大家好! 問題1:HTTP請求和返回相應的HTTP響應信息之間發生了什麼? 1:首先是最底層,托管層,位於WebAPI和底層HTTP棧之間 2:其次是 消息處理程式管道層,這裡比如日誌和緩存。OWIN的引用是將消息處理程式管道的一些功能下移到棧下端的OWIN中間件了。 3:控制器處理 ...
  • 參考文檔: https://jingyan.baidu.com/article/ed15cb1bb5c3411be369819d.html https://blog.csdn.net/hzw19920329/article/details/53156015 https://blog.csdn.net ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...