上個星期,我們發布了我們的Visual Studio和.NET框架Orcas版三月份的CTP,這是個誰都可以下的免費下載,同時提供VPC鏡像(允許你在一個虛擬機里運行它)以及單獨的安裝文件(注:如果你在運行Vista的話,你要確認你只使用VPC版本)。你可以在這里下載。
幾個星期前,我曾在博客上討論過Orcas中針對ASP.NET開發人員的一些重大的改進。如果你還沒有讀過這個貼子的話,我強烈建議你在這里讀一下。我認為你會非常喜歡該帖子討論的新特性的。
除了那些框架和工具類的精彩新特性外,我認為開發人員(包括所有的.NET應用類型的開發人員)會非常喜愛Orcas的一件事情是,VB和C#將包含一些新語言特性和改進。這些語言改動將以既微妙又深刻的方式改進我們的開發體驗,勢將改進效率,減小我們需要鍵入的代碼量。
在下幾個星期里,我將試著在博客里討論幾個這些語言的改進之處,示范如何把它們使用在一起,來產生一些非常強有力的結果。
新的C#語言特性:自動屬性(Automatic Properties)
如果你現在是C#開發人員的話,你大概非常習慣編寫象下面這個代碼片段一樣帶有基本屬性的類型:
private string _firstName;
private string _lastName;
private int _age;
public string FirstName {
get {
return _firstName;
}
set {
_firstName = value;
}
}
public string LastName {
get {
return _lastName;
}
set {
_lastName = value;
}
}
public int Age {
get {
return _age;
}
set {
_age = value;
}
}
}
注意,我們在屬性的geter/setter中實際上并沒有添加什么邏輯,我們只是將get/set實施到了一個成員變量。我們不禁要問這樣一個問題:為什么不直接使用成員變量而使用屬性呢?這是因為,向外面呈現公開的成員變量有很多不好的地方。二個最大的問題是:1) 你無法輕易地對成員變量做數據綁定,2) 如果你從類中向外呈現成員變量的話,之后,你不重新編譯那些引用老的類的任何程序集,就無法將它們改成屬性(譬如,要添加驗證邏輯到setter里)。
Orcas中發布的新C#編譯器通過一個叫“自動屬性(automatic properties)”的語言特性提供了一個優雅的方式來使得你的編碼更加簡潔,同時還保持屬性的靈活性。自動屬性允許你避免手工聲明一個私有成員變量以及編寫get/set邏輯,取而代之的是,編譯器會自動為你生成一個私有變量和默認的get/set 操作。
譬如,使用自動屬性,我現在可以將上面的代碼改寫成:
public string FirstName {
get; set;
}
public string LastName {
get; set;
}
public int Age {
get; set;
}
}
或者,我想更簡明的話,我可以將空白的地方做進一步壓縮,象這樣:
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
當Orcas版中的C#編譯器遇上象上面這樣的空的get/set屬性的話,它會自動為你在類中生成一個私有成員變量,對這個變量實現一個公開的getter 和setter。這么做的好處是,從類-合同(type-contract)的角度來看,這個類跟我們上面第一個有點冗長的實現看上去完全一樣,這意味著,不象公開的成員變量,在將來,我可以在我的屬性setter實現中添加驗證邏輯,而不用對引用我的類的任何外部組件做改動。
Bart De Smet對使用Orcas三月份CTP版中的自動屬性時內部發生的情形作了精彩的描述,你可以在這里閱讀他的精彩相關帖子。
C#和VB語言的新特性:對象初始化器(Object Initializers)
.NET框架中的類型非常依賴于屬性的使用。當生成對象實例和使用新的類型時,寫出象下面這樣的編碼是非常常見的情形:
person.FirstName = "Scott";
person.LastName = "Guthrie";
person.Age = 32;
你有沒有想要把這樣的編碼簡化過(也許將其安排在一行上)?使用Orcas中的C#和VB語言編譯器的話,你現在可以利用一個稱為“對象初始化器(object Initializers)”的“語法甜頭(syntactic sugar)”語言特性來做些簡化,將上述代碼重寫為:
然后,編譯器就會自動地生成合適的屬性setter代碼,保持跟前面較冗長的代碼例子同樣的語意。
除了在初始化類時設置簡單的屬性值外,對象初始化器特性也允許我們設置更復雜的嵌套(nested)屬性類型。譬如,假如我們在上面定義的每個Person類型也擁有一個屬于Address類型的叫“Address”的屬性。我們可以編寫下面這樣的代碼來生成一個新的Person對象,同時設置它的屬性,象這樣:
FirstName = "Scott",
LastName = "Guthrie"
Age = 32,
Address = new Address {
Street = "One Microsoft Way",
City = "Redmond",
State = "WA",
Zip = 98052
}
};
Bart De Smet對使用Orcas三月份CTP版中的對象初始化器時內部發生的情形也作了精彩的描述,你可以在這里閱讀他的精彩相關帖子。
C#和VB語言的新特性:集合初始化器(Collection Initializers)
對象初始化器很棒,它極大地簡化了把對象添加到集合的做法。譬如,假如我要把三個人加到一個基于泛型的類型為Person的List集合中去的話,我可以寫下面這樣的編碼:
people.Add( new Person { FirstName = "Scott", LastName = "Guthrie", Age = 32 } );
people.Add( new Person { FirstName = "Bill", LastName = "Gates", Age = 50 } );
people.Add( new Person { FirstName = "Susanne", LastName = "Guthrie", Age = 32 } );
對這個例子,跟我使用C# 2.0編譯器要輸入的代碼相比,單獨使用新的對象初始化器特性就能省去12行額外的代碼。
但Orcas版中的C#和VB編譯器允許我們更進一步,現在同時支持“集合初始化器(collection initializers)”,這允許我們避免要寫多個Add語句,省下更多的鍵盤操作:
new Person { FirstName = "Scott", LastName = "Guthrie", Age = 32 },
new Person { FirstName = "Bill", LastName = "Gates", Age = 50 },
new Person { FirstName = "Susanne", LastName = "Guthrie", Age = 32 }
};
當編譯器遇上上面這樣的句法時,它會自動為我們生成象前面的例子一樣的集合插入編碼。
結語
作為開發人員,我們現在擁有了簡明得多的方式來定義對象,對它們初始化,將它們加入集合內。在運行時,其語意,跟今天的較長的版本的語意,是完全一樣的(所以你不必擔心行為會改變)。但現在你不需輸入那么多字符了,你的代碼將既干凈又簡明。
在不遠的將來,我將發表更多的博客貼子來討論Orcas版中更多的語言上的改進,包括擴展方法(Extension Methods),Lambdas和匿名類。然后,我將對LINQ做深入討論,示范它是如何利用所有這些特性來提供一個非常優雅的方式來查詢和與數據交互的。