C#3.0新特性(二)- 初始值設定項

一、自動屬性:

  在C# 2.0中,我們對成員進行封裝,也就是自動屬性,如下示例:

private int m_one;
public int One
{
  get { return m_one; }
  set { m_one = value; }
}

這種方式只需寫第一句代碼,然後用Visual Studio的Refactor->Encapsulate Field功能,很方便,也早已經爲大家熟知。而在C# 3.0中,我們只需要寫成如下一句就可以了:

public int Dne { get; set; }// Auto-implemented properties

可以看出,C# 3.0中這種自動屬性對C# 2.0中的屬性寫法作了大大的簡化。C# 3.0的自動屬性就不需要創建私有變量,而把這個工作交給編譯器代勞!當然,如果需要在獲取訪問器get或設置訪問器set裏頭添加一些邏輯,擴展也很方便。


  二、對象初始值設定項
  使用對象初始值設定項可以在創建對象時向對象的任何可訪問的字段或屬性分配值,而無需顯式調用構造函數。對象初始值設定項,我在很多地方看到,其名稱,又叫對象初始化器。看實例,以前,我們首先定義一個類:

public class MyClass
{
  public string Number { get; set; }
  public string Name { get; set; }
  public MyClass()
  {
  }
  public MyClass(string newID)
  {
    Number = newID;
  }
  public MyClass(string newID, string newName)
  {
    Number = newID;
    Name = newName;
  }
}

然後,new一個對象,並對其屬性初始化:

public static void newObject()
{
  MyClass cobject = new MyClass();
  cobject.Name = "yy";
  cobject.Number = "1111";
  MyClass dobject = new MyClass("1111");
  dobject.Name = "yy";
  MyClass eobject = new MyClass("1111","yy");
}

現在,在C# 3.0中,利用對象初始化器,new一個對象,並對可以訪問的屬性初始化,只需要如下一句代碼:

MyClass nobject = new MyClass{Name = "yy",Number = "1111"};

該屬性的類的定義如下:

public class OClass
{
  public string addr { get; set; }
  public string zip { get; set; }
  public OClass()
  {
  }
  public OClass(string address, string zipCode)
  {
    this.addr = address;
    this.zip = zipCode;
  }
}

然後,在newObject方法中,new一個新對象完全可以這樣做:


MyClass nestobject = new MyClass
{
  Name = "yy",
  Number = "1111",
  oclassMember = new OClass
  {
    addr = "neijiang",
    zip = "404045"
  }
};

使用了這麼多,需要注意的也還是有:
  自動屬性中,get和set後都有分號,花括號後邊沒有,二在對象初始化器的使用中,花括號中對各個屬性賦值時用逗號隔開,花括號結束了用分號。本質原因,自動屬性是屬性定義,按C# 2.0語法,get和set分別相當於一個語句,花括號相當於方法的開始和結束。而使用對象初始化器,相當於使用花括號來調用其構造函數,整個new的過程相當於一條語句。
  在使用對象初始化器設置嵌套的屬性類型的時候,內層嵌套的屬性用對象初始化器後的花括號後也是用逗號,而不是用分號。如果這嵌套的屬性放在了最後,則不用,如上例。

不管是嵌套的屬性,或者不嵌套的屬性,或者被嵌套的屬性,使用對象初始化器,要去該對象所屬的類必須提供沒有參數的構造函數,否則會報錯:does not contain a constructor that takes '0' arguments。
  使用對象初始化器時,花括號中對屬性賦值的順序可以交換,如:

MyClass nestobject1 = new MyClass
{
  Name = "yy",
  oclassMember = new OClass
  {
    addr = "neijiang",
    zip = "404045"
  },
  Number = "1111"
};
也是對的。


三、將對象初始值設定項用於匿名類型
  查詢表達式經常使用匿名類型,而這些類型只能使用對象初始值設定項進行初始化。如:

MyClass[] ojbset = new MyClass[12];
var vaobj =
  from obj in ojbset
  select new { obj.Name, obj.Number };
也就是說,把objset中的每一個obj的Name屬性和Number屬性拿來,new成新隱式類型,賦值給vaobj,這種新類型的屬性名也被省略掉了,那實際上,其屬性名就是Name和Nnumber,值分別是它們兩者的值。這個方式呢,由於new { obj.Name,obj.Number };這句是new的一個新的隱式類型,與類MyClass沒有關係,所以,MyClass沒有無參構造函數也是可以的。而如果要在new隱式類型的時候,重新命名其屬性,則可以採用如下方式:

var varobj =
  from vobj in ojbset
  select new { vobj.Name, ID = vobj.Number };

四、集合初始值設定項
  集合初始值設定項,也叫集合初始化器,會對初始化器中的元素進行按序調用ICollection<T>.Add(T) 。使用集合初始值設定項的對象的類型必須實現了System.Collections.Generic.ICollections<T>接口並指定了確定的T。使用它可以在初始化一個實現了IEnumerable的集合類時指定一個或多個元素初始值;
  元素初始值設定項可以是簡單的值,也可以是表達式或對象初始值設定項;
  通過使用集合初始值設定項,無需在源代碼中指定多個對該類的Add 方法的調用;編譯器會添加這些調用。
  例子如下:

public void setinit()
{
  List<int> digits = new List<int> {
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9
  };
  List<int> digits2 = new List<int> {
    0 + 1, 12 % 3, getIntNumber()
  };
  List<MyClass> customers = new List<MyClass>{
    new MyClass{Number="1111",Name="yy"},
    new MyClass{Number="2222",Name="qq"},
    new MyClass{Number="3333",Name="qiqi"}
  };
}
public int getIntNumber()
{
  return 56;
}

這和以前調用List.Add沒有本質的區別,編譯器自動的調用了List的無參構造方法,然後實例化一個個的MyClass,再一個個的Add進去,和我們原來的做法沒有什麼不同,但是,這是編譯器在後臺自動處理,簡省了我們很多的編碼工作。
  注:
  各項之間還是用逗號,結束了,花括號後邊表示new這個集合結束,用分號。
  如果集合的Add 方法允許,可以將null 指定爲集合初始值設定項中的一個元素。如:

List<MyClass> customers = new List<MyClass>{
  new MyClass{Number="1111",Name="yy"},
  new MyClass{Number="2222",Name="qq"},
  new MyClass{Number="3333",Name="qiqi"},
  null
};

五、總結
  這些新特性平常怕是很少用到的,因爲已經習慣了C# 2.0的寫法,而且,這樣寫又不是必須的。但真正熟悉了,編譯器已經幫開發人員做了越類越多的工作,從而節約了我們的開發時間。或許,在其它的應用當中,這樣的語法還能用的到吧。


來源: 博客園   作者:山高月大

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章