為了以後複習和尋找,花了一些時間整理一下C# 3.0的語言新特性:
一、隱含類型局部變數
var i=5
var h=23.43
var s="C sharp"
var intArray=new[] {1,2,3,4}
var a=new[] {1,10,100,1000}
注意:
1.var為關鍵字,可以根據後面的初始化語句自動推斷類型。
2.初始化語句必須是運算式,且在編譯器可以推斷類型。
3.var不是一個類型,也不是類型相容,可以把它看成一個預留位置,編譯時間會自動替換成一個強型別(不是Object)。
4.var s=null 編譯錯誤(null沒類型),編譯器不能自動推斷s的類型。
5.初始化器不能是一個對象,也不是一個集合,只能是一個運算式,只有根據運算式才能推斷它的類型。var s也是不正確的。
6.var 聲明的僅限於局部變數,也可以用於foreach,using等語句中。
7.為了避免變數出現var這個變數(var關鍵字優先),遵循Code Standard規範。
8.數組也可以作為隱含類型。(數組初始化器的類型必須是一致的,編譯器不能為不同類型初始化器編譯後產生Object[],編譯器不能轉換,編譯錯誤)
9.它是一個編譯時間的技術,只能用在local var(函數級)範圍。
二、擴充方法
public static class Extensions{
public static void StringTrim(this string s){
..
}
}
調用
string s="Hello,Charles Chen";
s.StringTrim();
編譯器編譯後會產生Extensions.StringTrim(s);
補充:
class Person{public void Bar(){...}}
Person p=new Person();
p.Bar();
編譯器編譯後會產生:p.Bar()------>Bar(p)
Class Person{public void Bar(){...}}-------->void Bar(Person this){...}(全域函數)
這就是為什麼在執行個體函數可以訪問this指標,靜態函數就不能(不是這樣編譯的)。
這是IL代碼的編譯過程.(第一階段編譯過程還遵循對象的規範)。
分析S.StringTrim()------>Extensions.stringTrim(S),
我們應該怎樣看這個S對象呢?其實從物件導向的角度看是一個調用對象。而編譯器看到到了是一個參數,這樣從調用對象轉換成參數。
從而實現:擴充方法允許我們在不改變原始碼的情況下擴充(添加)現有類型中的執行個體方法。
這樣不改變原始碼的情況下,增加新的執行個體方法。注意Extensions必須是靜態類.
注意:
1.本質:將執行個體方法調用在編譯期改變為靜態類中的靜態方法調用。
2.擴充方法的優先順序:現有執行個體方法優先順序最高,其次為最近的namespace下靜態類中的靜態方法,最後為較遠的namespace下的靜態類的靜態方法。(如果2個一樣遠,則編譯error)
3.擴充方法是一種編譯時間技術,注意與反射等運行時技術進行區別,並謹慎使用。
4.當需要對CLR類型進行一些操作,但苦於無法擴充CLR類型的方法,只能建立一些helper方法時,就可以運用擴充方法。
三、對象和集合初始化器
1.對象初始化器
public class Point
{
int x,y;
public int X{get{return x;} set{x=value;}}
public int Y{get{return y;}set{y=value;}}
}
var a=new Point{X=2,Y=1}
相當於:var a=new Point();a.X=2;a.Y=1;
2.集合初始化器
List<int> num=new List<int>{1,2,3,4,5};實際上編譯器內部是調用List.Add()方法來初始化。
注意:
1.對象初始化器實際上利用了編譯器對對象中對外可見的欄位和屬性進行按序賦值。
2.集合初始化器會對初始化器中的元素進行按序調用ICollection<T>.Add(T).
3.注意對象的初始化器和集合初始化器中的成員的可見度和調用順序。
4.對象與集合的初始化器同樣是一種編譯器技術。
四、匿名型別
var p1=new {Name="Charles";Sex="男"}
var p2=new {Name="Changchang",Sex="男"}
p1=p2
編譯後:
class SomeType
{
private string _name;
private string _sex;
public string Name{get;set}
public string Sex{get;set}
}
注意:
1.可以使用new關鍵字調用匿名初始化器建立的一個匿名型別的對象。
2.匿名型別直接繼承自System.Object。
3.匿名型別的成員是編譯器根據初始化器推斷而來的一些讀寫屬性。
4.局部範圍類使用,就可以用匿名型別。
5.在同一段程式(局部範圍)內。(2個申明同樣的類型在編譯後是同一類型。(如上的P1=P2))。