隱式類型和對象集合初始化器是在C# 3.0中引入的。
1 隱式類型
var關鍵字,主要還是編譯器根據變量的值來推斷其類型。
1.1隱式類型的局部變量
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 var stringvariable="learning hard"; 6 stringvariable=2; 7 } 8 }
其實當你把鼠標放在var上面的時候,還是可以看到其類型的。
使用隱式類型時有一些限制,包括一下幾點:
(1)被聲明的變量是一個局部變量,不能為字段(包括靜態字段和實例字段)。
(2)變量在聲明時必須被初始化,因為編譯器要根據變量的賦值來推斷類型,如果未被初始化,編譯器也就無法完成推斷了。C#是靜態語言,變量類型未知就會出現編譯時錯誤。
(3)變量不能初始化為一個方法組,也不能為一個匿名函數。
(4)變量不能初始化為null,因為null可以隱式地轉化為任何引用類型或可空類型,編譯器將不能推斷出該變量到底為什麼類型。
(5)不能用一個正在聲明的變量來初始化隱式類型。如以下代碼:
string s; var stringvariable=s;
(6)不能用var來聲明方法中的參數類型。
其實我個人建議不要在程序中用過多的var,如果能有類型的就指定類型,這樣的代碼更讓別人看懂。
1.2 隱式類型數組
使用var關鍵字不僅可以創建隱式類型局部變量,還可以創建數組。
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 var intarray=new[]{1,2,3,4} 6 var stringarray=new[]{"hello","learning hard"}; 7 //下面是錯誤的示范代碼 8 var errorarray=new[]{"hello",3}; 9 } 10 }
使用隱式類型的數組時,編譯器也必須要能推斷出數組的類型。編譯器首先會構造一個包含大括號裡所有表達式的編譯時類型的集合。在這個集合中,如果所有類型都能隱式地轉換為唯一的一種類型,則該類型就成為數組的類型;否則,就會出現編譯時錯誤。
2、對象集合初始化器
2.1 對象初始化器
啥都不說,先上代碼:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Person p = new Person() {Name = "Hong", Age = 25, Weight = 65, Height = 170}; 6 } 7 } 8 9 public class Person 10 { 11 public string Name { get; set; } 12 public int Age { get; set; } 13 public int Weight { get; set; } 14 public int Height { get; set; } 15 }
其實這又是編譯器在幫忙,我們不妨用Reflector看一下:
注意:要想用對象初始化器,你必須確保類具有一個無參構造函數。如果你自定了一個有參數的構造函數而把默認的無參構造函數覆蓋,就需要重新定義一個無參構造函數。
2.2 集合初始化器
其實原理和上面的對象初始化器一樣,可以利用Reflector反編譯查看。
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 List<string> newnames=new List<string>{"111","2222","4433"}; 6 } 7 }
3、匿名類型
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 var person = new {Name = "Hong", Age = 12}; 6 Console.WriteLine($"{person.Name}的年齡為:{person.Age}"); 7 8 var persons = new[] 9 { 10 new {Name = "1", Age = 2}, 11 new {Name = "2", Age = 3}, 12 new {Name = "3", Age = 4} 13 14 //如果加入下面這一行,則會編譯錯誤 15 //new {Name="6"} 16 }; 17 int totalAge = persons.Sum(per => per.Age); 18 Console.WriteLine($"所有人的年齡總和為{totalAge}"); 19 Console.ReadKey(); 20 } 21 }
結果為:
從運行結果和匿名類型的代碼可知,使用匿名類型可以省略類定義的代碼。使用Reflector查看一下反編譯的結果: