C#学习笔记四: C#3.0自动属性匿名属性及扩展方法
前言
這一章算是看這本書(shū)最大的收獲了, Lambda表達(dá)式讓人用著屢試不爽, C#3.0可謂顛覆了我們的代碼編寫(xiě)風(fēng)格. 因?yàn)長(zhǎng)ambda所需篇幅挺大, 所以先總結(jié)C#3.0智能編譯器給我們帶來(lái)的諸多好處, 下一遍會(huì)單獨(dú)介紹Lambda表達(dá)式. 這篇主要包括的內(nèi)容有:?自動(dòng)屬性,隱式類型,對(duì)象集合初始化,匿名類型,擴(kuò)展方法.
下面一起來(lái)看下C#3.0 所帶來(lái)的變化吧.
1,自動(dòng)實(shí)現(xiàn)的屬性
在C#3.0之前, 定義屬性時(shí)一般會(huì)像下面這樣去編寫(xiě)代碼:
PS: 這里有一個(gè)快捷鍵: private string name; 選中name 然后Ctrl + R + E 就可以快捷生成Name屬性.
C#3.0之后, 對(duì)于不需要額外驗(yàn)證的屬性(需要額外驗(yàn)證的屬性還是必須采用之前的方式來(lái)定義), 我們可以使用自動(dòng)實(shí)現(xiàn)的特性來(lái)對(duì)屬性的定義進(jìn)行簡(jiǎn)化, 此時(shí)不再需額外定義一個(gè)私有字段了.代碼如下:
1 class Person 2 { 3 //使用自動(dòng)實(shí)現(xiàn)的屬性來(lái)定義屬性 4 //定義可讀寫(xiě)屬性 5 public string Name{get; set;} 6 //定義只讀屬性 7 public int Age{get; private set;} 8 } View CodePS: 這里也有一個(gè)快捷鍵: 打出prop 然后點(diǎn)擊兩下Tab鍵就可以生成上面的屬性了, 不過(guò)還需手動(dòng)改值.?
類似的快捷鍵有: 輸入cw 然后點(diǎn)擊兩下Tab鍵 就可以直接生成Console.WriteLine();了. 類似的還有很多, 在這里就不列舉了.
之所以可以這樣定義屬性, 主要是因?yàn)榫幾g器在編譯時(shí)會(huì)為我們創(chuàng)建一個(gè)私有字段. 利用反編譯工具可以知道使用自動(dòng)實(shí)現(xiàn)的屬性時(shí),C#都會(huì)幫我們創(chuàng)建必要的字段.
另外在結(jié)構(gòu)體中使用自動(dòng)屬性時(shí), 需要注意的是所有構(gòu)造函數(shù)都需要顯式地調(diào)用無(wú)參構(gòu)造函數(shù)this, 否則會(huì)出現(xiàn)編譯錯(cuò)誤. 因?yàn)橹挥羞@樣,編譯器才能知道所有的字段都已經(jīng)被賦值.
然而, 類卻不需要顯式地調(diào)用無(wú)參構(gòu)造函數(shù), 這主要是由C#編譯器的設(shè)計(jì)決定, 我們記住就好了.
2,隱式類型 var關(guān)鍵字
C#是強(qiáng)類型語(yǔ)言, 在定義一個(gè)變量時(shí), 需要聲明變量的類型. 然而類型的長(zhǎng)度過(guò)長(zhǎng),就可能影響代碼的可讀寫(xiě)性. 為了避免這樣的問(wèn)題, C#3.0 引入了隱式類型,即可以使用關(guān)鍵字var來(lái)聲明變量或數(shù)組.
var關(guān)鍵字告訴編譯器去根據(jù)變量的值來(lái)推斷其類型.
這里就會(huì)報(bào)錯(cuò)"無(wú)法將類型int 隱式轉(zhuǎn)換為string". 調(diào)試會(huì)發(fā)現(xiàn)stringValue是string類型的.
使用隱式類型有一些限制, 包括以下幾點(diǎn):
(1)被聲明的變量是一個(gè)局部變量, 不能為字段
(2)變量在聲明時(shí)必須被初始化, 因?yàn)榫幾g器要根據(jù)變量的賦值來(lái)推斷類型
(3)變量不能初始化為一個(gè)方法組, 也不能為一個(gè)匿名函數(shù)
3,對(duì)象集合初始化
在C#3.0之前定義類, 我們往往需要定義多個(gè)構(gòu)造函數(shù)來(lái)完成不同情況下的初始化, C#3.0 提供了對(duì)象初始化器, 它減少了我們?cè)陬愔卸x的構(gòu)造函數(shù)代碼, 從而使代碼更加簡(jiǎn)潔.
在C#3.0引入對(duì)象初始化之后, 我們就不需要定義多個(gè)構(gòu)造函數(shù)了, 前面的代碼可以簡(jiǎn)化為如下的形式:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //使用對(duì)象初始化器初始化 6 Person p = new Person() {Name = "Barry Wang", Age = 25, Weght = 60, Height = 70}; 7 //下面這行代碼和上面一行是等價(jià)的, 只不過(guò)下面省略了構(gòu)造函數(shù)的圓括號(hào)而已 8 Person p2 = new Person {Name = "Barry Wang", Age = 25, Weght = 60, Height = 70}; 9 } 10 } 11 12 public class Person 13 { 14 public string Name { get; set; } 15 public int Age { get; set; } 16 public int Weight { get; set; } 17 public int Height { get; set; } 18 } View Code利用反編譯工具可以知道編譯器為對(duì)象做了如下處理: 首先C#編譯器生成了一個(gè)Person類的臨時(shí)對(duì)象, 并調(diào)用Person類的默認(rèn)無(wú)參構(gòu)造函數(shù)對(duì)其初始化.然后對(duì)它的屬性逐個(gè)賦值.
由此可以想到,要使用對(duì)象初始化器,則必須保證類中具有一個(gè)無(wú)參構(gòu)造函數(shù). 如果我們自定義了一個(gè)有參構(gòu)造函數(shù)而把默認(rèn)的無(wú)參構(gòu)造函數(shù)覆蓋了, 則需要重新定義一個(gè)無(wú)參構(gòu)造函數(shù).
再例如 給List 中添加元素, 在C#3.0 之前我們需要一個(gè)個(gè)Add 添加, 而現(xiàn)在直接可以利用集合初始化器即可, 編譯器會(huì)調(diào)用Add方法, 一個(gè)個(gè)地將初始化的內(nèi)容添加進(jìn)去.
1 class Program 2 { 3 List<string> newNames = new List<string> 4 { 5 "A", "B", "C" 6 }; 7 } View Code4,匿名類型
匿名類型顧名思義就是沒(méi)有知名類型的類型, 通過(guò)隱式類型和對(duì)象初始化器兩種特性創(chuàng)建了一個(gè)類型未知的對(duì)象, 使我們?cè)诓欢x類型的情況下可以實(shí)現(xiàn)對(duì)象的創(chuàng)建,從而減少了類定義過(guò)程的代碼.
5,擴(kuò)展方法
擴(kuò)展方法, 首先是一個(gè)方法, 他可以用來(lái)擴(kuò)展已定義類型中的方法成員.
如下例所示:
并不是所有的方法都可以用作擴(kuò)展方法, 我們需要考察它是否符合下列擴(kuò)展方法的定義規(guī)則:
(1)擴(kuò)展方法必須在一個(gè)非嵌套, 非泛型的靜態(tài)類中定義
(2)它至少要有一個(gè)參數(shù)
(3)第一個(gè)參數(shù)必須加上this關(guān)鍵字作為前綴(第一個(gè)參數(shù)類型也稱為擴(kuò)展類型, 即指方法對(duì)這個(gè)類型進(jìn)行擴(kuò)展)
(4)第一個(gè)參數(shù)不能使用任何其他修飾符(如不能使用ref out等)
打印結(jié)果是:
調(diào)用的是當(dāng)前命名空間下的擴(kuò)展方法輸出, 姓名為: Barry Wang
調(diào)用的是CustomNameSpace命名空間下擴(kuò)展方法輸出, 姓名為: Barry Wang, 附加字符串為Hello
注解: 大家看到p.Print(); 是否有些疑惑呢? 對(duì)于C#3.0編譯器而言, 當(dāng)它看到某個(gè)類型的變量在調(diào)用方法時(shí), 它會(huì)首先去該對(duì)象的實(shí)例方法進(jìn)行查找,如果沒(méi)有找到與調(diào)用方法同名并參數(shù)一致的實(shí)例方法,
編譯器就回去查找是否存在合適的擴(kuò)展方法. 編譯器會(huì)檢查所有導(dǎo)入的命名空間和當(dāng)前命名空間中的擴(kuò)展方法, 并將變量類型匹配到擴(kuò)展類型.
從編譯器發(fā)現(xiàn)擴(kuò)展方法的過(guò)程來(lái)看, 方法調(diào)用的優(yōu)先級(jí)別順序?yàn)? 類型的實(shí)例方法-->當(dāng)前命名空間下的擴(kuò)展方法-->導(dǎo)入命名空間的擴(kuò)展方法.
解釋上面代碼打印結(jié)果的由來(lái): 在以上代碼中存在另個(gè)不同的命名空間, 它們都定義了帶一個(gè)參數(shù)的擴(kuò)展方法Print. 根據(jù)執(zhí)行順序, 編譯器會(huì)首先查看Person類型中是否定義了無(wú)參的Print實(shí)例方法.
如果有, 則停止查找; 否則繼續(xù)查找當(dāng)前命名空間下, 即CurrentNameSpace下是否定義了一個(gè)帶參數(shù)的擴(kuò)展方法Print.
此時(shí)在CurrentNameSpace命名空間下, 正好存在帶一個(gè)擴(kuò)展類型參數(shù)的Print擴(kuò)展方法, 編譯器因此不會(huì)再繼續(xù)查找其他引入命名空間了. 所以p.Print() 調(diào)用的是當(dāng)前命名空間下的Print擴(kuò)展方法.
而p.Print("Hello")的調(diào)用也是一個(gè)道理.
轉(zhuǎn)載于:https://www.cnblogs.com/xinhuawei/p/5409275.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的C#学习笔记四: C#3.0自动属性匿名属性及扩展方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 2016/4/19 ①单个文件上
- 下一篇: C# 实现一个可取消的多线程操作 示例