第七节:语法总结(1)(自动属性、out参数、对象初始化器、var和dynamic等)
一. 語(yǔ)法糖簡(jiǎn)介
? ??語(yǔ)法糖也譯為糖衣語(yǔ)法,是由英國(guó)計(jì)算機(jī)科學(xué)家彼得·約翰·蘭達(dá)(Peter J. Landin)發(fā)明的一個(gè)術(shù)語(yǔ),指計(jì)算機(jī)語(yǔ)言中添加的某種語(yǔ)法,這種語(yǔ)法對(duì)語(yǔ)言的功能并沒(méi)有影響,但是更方便程序員使用。通常來(lái)說(shuō)使用語(yǔ)法糖能夠增加程序的可讀性,從而減少程序代碼出錯(cuò)的機(jī)會(huì)。
? ? ? 需要聲明的是“語(yǔ)法糖”這個(gè)詞絕非貶義詞,它可以給我?guī)?lái)方便,是一種便捷的寫(xiě)法,編譯器會(huì)幫我們做轉(zhuǎn)換;而且可以提高開(kāi)發(fā)編碼的效率,在性能上也不會(huì)帶來(lái)?yè)p失。
? ? ? 在編譯器發(fā)展早期,編譯器科學(xué)家門(mén)一直在想方設(shè)法的優(yōu)化編譯器生成的代碼,這個(gè)時(shí)候,編譯器做的主要是對(duì)機(jī)器優(yōu)化,因?yàn)槟莻€(gè)時(shí)候機(jī)器的時(shí)間非常寶貴,機(jī)器運(yùn)算速度也不快,今天我們有了足夠好的機(jī)器了(但并不是說(shuō)我們可以不關(guān)注性能的編寫(xiě)程序),而且作為編寫(xiě)軟件的人來(lái)說(shuō),比機(jī)器的時(shí)間寶貴得多,所以今天的編譯器也在向人優(yōu)化了,從編程語(yǔ)言的發(fā)展之路來(lái)講,今天的編程語(yǔ)言比昨天的語(yǔ)言更高級(jí),也更人性化了,我們只要編寫(xiě)更少的代碼,更符合人的思維的代碼,而只要關(guān)注我們值的關(guān)注的地方。體力活兒就交給編譯器吧。
二. 常用語(yǔ)法糖
1. 自動(dòng)屬性
(1). ?傳統(tǒng)的方式在類(lèi)中聲明一個(gè)屬性,需要先聲明一個(gè)私有變量的字段,然后在配合公有屬性,如下面的:userId屬性。
(2). 利用自動(dòng)屬性:不需要字段,聲明一個(gè)空屬性,直接get,set(快捷鍵:prop),編譯時(shí)編譯器為我們生成存取數(shù)據(jù)的字段. 如下面的:userName屬性。
1 public class userInfor2 {3 //私有字段4 private string _userId;5 //公有屬性6 public string userId7 {8 get9 { 10 return _userId; 11 } 12 set 13 { 14 _userId = value; 15 } 16 } 17 18 public string useName { get; set; } 19 20 21 /// <summary> 22 /// 為了后面的反射調(diào)用 23 /// </summary> 24 public void Test() 25 { 26 Console.WriteLine("我是一個(gè)方法"); 27 } 28 29 }2. var和dynamic
(1). var類(lèi)型:聲明變量的時(shí)候可以不指定類(lèi)型,由編譯器編譯的時(shí)候來(lái)指定類(lèi)型。
①:必須在定義的時(shí)候初始化
②:必須是局部變量
③:一旦初始化完成,不能再給變量賦與初始值不同類(lèi)型的值了,但是可以賦相同類(lèi)型的不同值.
④:var在效率是和使用強(qiáng)類(lèi)型方式定義變量是一樣的
(2). dynamic類(lèi)型:編譯期間不做任何檢查,運(yùn)行期間才確定類(lèi)型。
①:定義的時(shí)候可以不必初始化
②:可以是全局變量,也可以是局部變量
? dynamic在反射中的應(yīng)用:通過(guò)反射拿到類(lèi)后,賦值給dynamic類(lèi)型,該類(lèi)型的對(duì)象可以直接點(diǎn)來(lái)調(diào)用方法
? 缺點(diǎn):dynamic在運(yùn)行的時(shí)候才進(jìn)行檢測(cè),導(dǎo)致編譯的時(shí)候即使有錯(cuò)誤也不會(huì)被發(fā)現(xiàn); 不能用dynamic類(lèi)型給確定類(lèi)型的變量進(jìn)行賦值
1 public class CompareTwo2 {3 //2. 可使用的范圍4 // var b1 = 1; //報(bào)錯(cuò),var必須定義在方法呃逆5 // dynamic b2 = 2; //正常6 public static void Show()7 {8 {9 //1. 初始化比較 10 //var a1; //報(bào)錯(cuò),定義的時(shí)候必須初始化 11 //dynamic a2; //正常 12 } 13 { 14 //3. 賦值問(wèn)題 15 var c1 = 2; 16 //c1 = "2"; //報(bào)錯(cuò),初始化完成不能賦值不同類(lèi)型的變量 17 c1 = 3; //正常,初始化完成可以賦值相同類(lèi)型的變量的不同值 18 19 dynamic d1 = 2; 20 d1 = "2"; //正常,運(yùn)行時(shí)檢查進(jìn)行類(lèi)型指定,所以在編譯的時(shí)候不會(huì)報(bào)錯(cuò) 21 d1 = 3; //正常 22 23 24 var userInfor = new userInfor(); 25 userInfor.useName = "1"; 26 userInfor.userId = "2"; 27 // userInfor.fk123(); //報(bào)錯(cuò),編譯不通過(guò) 28 29 dynamic userInfor2 = new userInfor(); 30 userInfor2.userId = "1"; 31 userInfor2.useName = "ypf"; 32 //調(diào)用不存在的方法 (因?yàn)榫幾g的時(shí)候根本不檢查,所以不會(huì)報(bào)錯(cuò),運(yùn)行的時(shí)候報(bào)錯(cuò)) 33 //userInfor2.fk123(); //編譯期間不報(bào)錯(cuò),運(yùn)行的時(shí)候報(bào)錯(cuò) 34 35 } 36 { 37 //4. dynamic在反射中的應(yīng)用 38 //4.1 常規(guī)反射調(diào)用方法 39 Type type1 = typeof(userInfor); 40 object oStudent = Activator.CreateInstance(type1); 41 MethodInfo method = type1.GetMethod("Test"); 42 method.Invoke(oStudent,null); 43 44 //4.2 利用dynamic簡(jiǎn)化調(diào)用 45 //定義和編譯的時(shí)候可以是任何類(lèi)型,運(yùn)行的時(shí)候進(jìn)行轉(zhuǎn)換 46 dynamic oStudent2 = Activator.CreateInstance(type1); 47 oStudent2.Test(); 48 49 } 50 } 51 }3. 可選參數(shù)
給方法的參數(shù)可以指定默認(rèn)值,如果在調(diào)用該方法的時(shí)候,不傳入該參數(shù),則走默認(rèn)值,傳入的話(huà),則覆蓋默認(rèn)參數(shù).
(1). ?有默認(rèn)值的參數(shù)必須定義在沒(méi)有默認(rèn)值的參數(shù)之后
(2). ?默認(rèn)參數(shù)必須是常量,不能是變量
(3). ?ref和out參數(shù)不能指定默認(rèn)值
1 public class OptionalParas 2 { 3 public static void Test(string useName,string userPwd,int userAge=16,string userSex="男") 4 { 5 Console.WriteLine("userName:{0},userPwd:{1},userAge:{2},userSex:{3}", useName, userPwd, userAge, userSex); 6 } 7 } 1 //3.可選參數(shù) 2 Console.WriteLine("----------------------3.可選參數(shù)-------------------------"); 3 OptionalParas.Test("ypf1", "123456"); 4 OptionalParas.Test("ypf2", "654321", 56, "女");4. 對(duì)象(集合)初始化器
1 public class ObjectInitilize2 {3 public static void Test()4 {5 6 //一.對(duì)象初始化7 //1. 傳統(tǒng)初始化對(duì)象的方式8 userInfor uInfor1 = new userInfor();9 uInfor1.userId = "1"; 10 uInfor1.useName = "ypf1"; 11 12 //2.對(duì)象初始化器 13 userInfor uInfor2 = new userInfor() 14 { 15 userId="2", 16 useName="ypf2" 17 }; 18 userInfor uInfor3 = new userInfor() 19 { 20 userId = "3", 21 useName = "ypf3" 22 }; 23 24 //二. 集合初始化 25 //1. 傳統(tǒng)方式 26 List<userInfor> uList = new List<userInfor>(); 27 uList.Add(uInfor1); 28 uList.Add(uInfor2); 29 30 //2. 集合初始化器 31 List<userInfor> uList2 = new List<userInfor>(){ 32 uInfor1, 33 uInfor2, 34 new userInfor(){ 35 userId="4", 36 useName="ypf4" 37 } 38 }; 39 40 } 41 }5. ref和out
二者共同的使用場(chǎng)景,將ref或out參數(shù)傳入方法中,執(zhí)行完方法后,可以直接使用ref或out參數(shù)值。
(1). ref必須在使用前賦值,即傳入方法前進(jìn)行定義并賦值
(2). out必須在方法中賦值然后使用,在調(diào)用方法前聲明兩個(gè)未實(shí)例化的變量,用來(lái)傳入和接收使用
舉例:有兩個(gè)int類(lèi)型的值num1和num2,分別使用ref和out傳入對(duì)應(yīng)的方法中,進(jìn)行值交換。
1 public class CompareRO2 {3 /// <summary>4 /// ref的使用5 /// </summary>6 public static void TestRef()7 {8 int num1 = 5;9 int num2 = 10; 10 Func1(ref num1, ref num2); 11 Console.WriteLine("num1的值為:{0},num2的值為:{1}", num1, num2); 12 } 13 14 public static void TestOut() 15 { 16 int num1; 17 int num2; 18 Func2(out num1, out num2); 19 Console.WriteLine("num1的值為:{0},num2的值為:{1}", num1, num2); 20 } 21 22 #region ref版參數(shù)值交換 23 public static void Func1(ref int n1, ref int n2) 24 { 25 int a = n1; 26 n1 = n2; 27 n2 = a; 28 } 29 #endregion 30 31 #region out版參數(shù)值交換 32 public static void Func2(out int n1,out int n2) 33 { 34 n1 = 5; 35 n2 = 10; 36 int a = n1; 37 n1 = n2; 38 n2 = a; 39 } 40 #endregion 41 42 }6. 匿名類(lèi)/匿名方法
?
? 詳見(jiàn):.Net進(jìn)階系列(3)-匿名類(lèi)、匿名方法、擴(kuò)展方法
?
7. 擴(kuò)展方法
?
? 詳見(jiàn):.Net進(jìn)階系列(3)-匿名類(lèi)、匿名方法、擴(kuò)展方法
總結(jié)
以上是生活随笔為你收集整理的第七节:语法总结(1)(自动属性、out参数、对象初始化器、var和dynamic等)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 有车没工作可以办信用卡吗
- 下一篇: 第五节 盒子模型