今天的篇幅應(yīng)該會(huì)很長(zhǎng),除了回顧前面學(xué)的一些,還有寫一些關(guān)于匿名類型的相關(guān)知識(shí),總體上對(duì)后續(xù)的學(xué)習(xí)很有幫助,學(xué)好了,后面更容易理解,不明白的,那就前面多翻幾次,看多了總是會(huì)理解的。那么,進(jìn)入正題吧。
我們的很多工作都是由編譯器幫我們?nèi)ネ瓿桑缥覀円f的自動(dòng)實(shí)現(xiàn)屬性。使用自動(dòng)實(shí)現(xiàn)屬性時(shí),C#3執(zhí)行了一個(gè)簡(jiǎn)單的編譯轉(zhuǎn)換,在類的內(nèi)部生成一個(gè)私有的字段,使用不友好的命名(防止命名沖突)。在C#2中允許為取值和賦值方法指定不同的訪問權(quán)限,現(xiàn)在我們還可以創(chuàng)建靜態(tài)的自動(dòng)屬性。
使用隱式類型,在編寫代碼時(shí),沒有顯式地聲明類型,但在編譯的結(jié)果中,編譯器會(huì)獲取初始化表達(dá)式的類型,使用變量也具有該類型。隱式類型只有在以下幾種情況才能使用:
一種方法是使用無參的構(gòu)造函數(shù)先實(shí)例化一個(gè)對(duì)象,然后分別為每個(gè)公開的屬性賦值。另一種則是在構(gòu)造函數(shù)中將屬性值作為參數(shù),在構(gòu)造函數(shù)中為每個(gè)屬性賦值,這里可以給公開和私有的賦值。使用自動(dòng)實(shí)現(xiàn)屬性,則可以使用對(duì)象初始化器,如下,三個(gè)類Computer、Mouse、User
1 class Computer 2 { 3 public string Cpu { get; set; } 4 public Mouse Mouse { get; set; } 5 public List<User> Users { get; set; } 6 } 7 class Mouse 8 { 9 public string Brand { get; set; }10 }11 class User12 {13 public string Name { get; set; }14 }
上述三個(gè)類都沒有構(gòu)造函數(shù)(有一個(gè)默認(rèn)的無參構(gòu)造函數(shù)),使用對(duì)象初始化器就能很方便的去實(shí)例化對(duì)象。
1 Computer c = new Computer() 2 { 3 Cpu = "AMD", 4 Mouse = new Mouse() { Brand = "羅技" }, 5 Users = new List<User> { 6 new User() {Name="小A" }, 7 new User() {Name="小B" }, 8 new User() {Name="小C" } 9 }10 };
可以看到上述的每一個(gè)對(duì)象實(shí)例都使用了對(duì)象初始器來實(shí)例化對(duì)象,調(diào)用的構(gòu)造函數(shù)都是系統(tǒng)默認(rèn)的構(gòu)造函數(shù),當(dāng)我們將無參的構(gòu)造函數(shù)設(shè)置為私有時(shí),上述語句將無效。那我們就可以想像,當(dāng)有一個(gè)為Cup賦值的構(gòu)造函數(shù),則在new Computer(cupName)接大括號(hào)"{}"來初始化對(duì)象,如
1 class Computer 2 { 3 public string Cpu { get; set; } 4 public Mouse Mouse { get; set; } 5 public List<User> Users { get; set; } 6 public Computer(string cpu) { 7 this.Cpu = cpu; 8 } 9 public Computer()10 {11 12 }13 }14 15 Computer c1 = new Computer("AMD")16 {17 Mouse = new Mouse() { Brand = "羅技" },18 Users = new List<User> {19 new User() {Name="小A" },20 new User() {Name="小B" },21 new User() {Name="小C" }22 }23 };
注:調(diào)用無參的構(gòu)造函數(shù)時(shí),使用省略類名后面的括號(hào)。
是不是看上面的代碼不斷是很多,那我們可以再精簡(jiǎn)一下new List<User>,和new Mouse。
1 Computer c1 = new Computer("AMD")2 {3 Mouse = { Brand = "羅技" },4 Users = {5 new User() {Name="小A" },6 new User() {Name="小B" },7 new User() {Name="小C" }8 }9 };
我們直接將類型名稱給去除了,看到這里是否也想到可以把new User也給去除了,不過我試過是不行的,應(yīng)該是無法確定要轉(zhuǎn)換的類型吧。這個(gè)有點(diǎn)類似在C++11中統(tǒng)一使用"{}"來初始化對(duì)象。關(guān)于集合初始化可以參照上述中的對(duì)屬性Users的初始化,而上述中Mouse = { Brand = "羅技" }則稱呼為初始化嵌入對(duì)象。
在C#1和C#2中,數(shù)組的聲明和初始化如下
1 string[] names = { "a", "b", "c" };
如果一個(gè)方法的簽名如下:
1 public void Method0(string[] names)
那使用大括號(hào)中的表達(dá)式不能作為參數(shù)傳入該方法,如
1 Method0({ "a", "b", "c" });
必須要告訴編譯器傳入的數(shù)組是什么類型的數(shù)組,如
1 Method0(new string[] { "a", "b", "c" });
但如果我們顯式的指定類型,可以讓編譯器自己推斷,則用到了隱式類型數(shù)組,里面也有涉及到協(xié)變性,如果A繼承于B,參數(shù)為A的數(shù)組,那么我們使用隱式類型的數(shù)組,就可以傳入A實(shí)例和B實(shí)例的數(shù)組。如:
1 class A 2 { 3 } 4 5 class B : A 6 { 7 } 8 9 public static void Method1(A[] args)10 {11 12 }13 14 A a = new A();15 B b = new B();16 Method1(new[] { a, b });17 Method1(new[] { new A(), new B() });
匿名類型常用作用于LINQ中返回一系列的沒有具體類型名的對(duì)象,也可以使用單獨(dú)使用(在不想創(chuàng)建多余的類時(shí))。
1 var p = new { Name = "a", Age = 12 };
接下來,就可以使用變量p,p有兩個(gè)屬性Name="a"和Age=12,也可以使用匿名類型來初始化數(shù)組,如
1 var ps = new[] {2 new { Name = "a", Age = 12},3 new { Name = "a", Age = 12},4 new { Name = "a", Age = 12}5 };
匿名類型包含以下成員:
關(guān)于投影初始化程序,簡(jiǎn)單地理解從一個(gè)集合中,抽取集合元素中的各別屬性,組成一個(gè)匿名類型,從而返回一個(gè)包含匿名類型的集合,這也是為什么我們使用var關(guān)鍵字,因?yàn)槲覀冋娴牟恢婪祷氐念愋停褂胿ar讓編譯器替我們理解返回類型,那問題來了,這個(gè)匿名類型的聲明是否由編譯器幫我們生成?它幫我們生成了類型,使用反編譯工具就能知曉。
請(qǐng)斧正。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注