1.隱型局部變量
c# 3.0引入了一個叫做“var”的新關(guān)鍵字。這個關(guān)鍵字允許開發(fā)者建立一個變量,但不必明確它的類型。例如,用var說明一個字符串,就像這樣:
varmydata = "this is my data";
注意,這里并沒有提到mydata變量是一個字符串,而c# 2.0卻要求這一點(diǎn)。
雖然var允許您建立隱含的類型,它并沒有降低c#濃厚的類型特征。var關(guān)鍵字只有在建立變量時有用,一旦您建立變量并且確定它的類型以后,就不能再用var來改變一個變量的類型。
例如,這段代碼沒有作用:
varmydate = datetime.now;
mydate = "hello.";
使用var關(guān)鍵字還會產(chǎn)生一個有趣的結(jié)果,它可以幫助開發(fā)者減少建立變量時的代碼輸入。例如,在c# 2.0中建立一個customer對象,需要輸入以下代碼:
customer mycustomer = new customer();
使用新的var關(guān)鍵字,則只要輸入:
varmycustomer = new customer();
var關(guān)鍵字的另一個特點(diǎn)在于,使用它可以避免改變一個返回某個類型對象的方法調(diào)用。例如,在c# 2.0中,如果您需要調(diào)用一個返回customer對象的方法,您應(yīng)該編寫以下代碼:
customer mycustomer = getbyname("zach");
如果某個時候getbyname方法返回一個不是customer的對象,這段代碼就無法編譯。但是,如果應(yīng)用var關(guān)鍵字,您就不用擔(dān)心getbyname返回的對象類型。
varmydata = getbyname("zach");
現(xiàn)在,因?yàn)閼?yīng)用了var關(guān)鍵字,getbyname方法能夠進(jìn)行改變,返回一個person對象,這個方法調(diào)用也依然有效。
2.extension方法
在c#中,您不能繼承和擴(kuò)充用訪問標(biāo)識符標(biāo)記為“封裝”的類型。但在c# 3.0中,extension方法允許您擴(kuò)充任何類,甚至是標(biāo)記為封裝的類。例如,如果希望添加一個nospaces()方法到字符串類中,我們要定義一個類似列表a中的extension方法。
列表a
namespacemyextensionmethods
{
public static class extension
{
public static void nospaces(this string data)
{
return data.replace(" ", "");
}
}
}
在一個類中導(dǎo)入這個extension方法時,開發(fā)者就能夠?qū)@個類包含的任何字符串調(diào)用nosapces()方法。
extension方法的第一個參數(shù)決定extension方法的有效類型。在這種情況下,“這個字符串?dāng)?shù)據(jù)”(this string data)表明extension方法適用于字符串類;如果extension方法以“這個對象數(shù)據(jù)”(this object data)為第一個參數(shù),則說明這個方法對每個對象有效。
要表明您希望導(dǎo)入extension方法,只需在它們的命名空間中包括一個using指令。例如,要應(yīng)用上面說明的方法,需要在類文件中包括一個using myextensionmethods指令:(列表b)
列表b
usingmyextensionmethods;
namespace mynamespace
{
public class myclass
{
public myclass()
{
string data = "this is my data";
//nospaces will contain "thisismydata".
string nospaces = data.nospaces();
}
}
}
注意extension方法的優(yōu)先度比instance方法低。因此如果instance方法和extension方法有同樣的簽名,則應(yīng)執(zhí)行instance方法。
3.對象初始化器
在c# 2.0中,開發(fā)者認(rèn)為建立許多構(gòu)造器來設(shè)定某個屬性值為對象初始化過程。下面是一個例子: 類訪問customer方法:
customer mycustomer = new customer("zach", "smith");
customer類構(gòu)造器:
public customer(string firstname, string lastname) : this()
{
this.firstname = firstname;
this.lastname = lastname;
}
public customer()
{}
c# 3.0介紹了一個初始化對象的新方法,它允許您在初始化對象時設(shè)定任何屬性值。例如,在c# 3.0中,上面的代碼塊可以寫成:
類訪問customer方法:
customer mycustomer = new customer{firstname = "zach", lastname = "smith" };
customer類構(gòu)造器:
public customer()
{}
在c# 3.0代碼中,沒有與初始化對象對應(yīng)的構(gòu)造器。這樣,開發(fā)者就不用為每組需要設(shè)定的屬性建立不同的構(gòu)造器。
這樣產(chǎn)生的另外一個效果是:代碼變得更容易閱讀了。例如,雖然我們清楚知道下面的代碼對一個car對象進(jìn)行了初始化,但我們并不清楚其中變量的作用:
car car = new car(18, 10, 550);
一眼看來,下面這行代碼更易閱讀,盡管我們必須輸入更多代碼:
car car = new car { wheeldiameter = 18, wheelwidth = 10, horsepower = 550 };
4.匿名類型
c# 2.0引入了匿名方法,c# 3.0推出匿名類型。匿名類型與匿名方法類似,它們都是以嵌入方式建立,并沒有正式的名稱。在建立一個匿名類型,您必須組合上述對象初始化器和隱型局部變量兩個概念。下面是一個匿名類型的例子:
varmytype = new { length = 79, width = 30 };
匿名類型的范圍與任何其它變量的范圍相同。例如,下面代碼塊中的cobra實(shí)例僅僅在speed函數(shù)塊中有效:
private void speed()
{
var cobra = new { horsepower = 550, torque = 570 };
}
如果一個匿名類型被初始化而另一個匿名類型位于范圍域中,并且它們的簽名相同,第二個類型將自己占用第一個類型的類型。例如,在下面這段代碼中,cobra和mustang都是匿名類型,并且可以彼此設(shè)定。
private void speed()
{
var cobra = new { horsepower = 550, torque = 570 };
var mustang = new { horsepower = 300, torque = 300 };
mustang = cobra; //or you could say cobra = mustang
}
5 .linq
在之前的c#版中,開發(fā)者應(yīng)用許多不同的查詢語言來訪問不同的數(shù)據(jù)源。例如,要查詢一個xml文件,開發(fā)者會使用xpath,要查詢一個sql數(shù)據(jù)庫,開發(fā)者將使用sql。在過去這種方法十分有效,并且現(xiàn)在仍然是訪問各種數(shù)據(jù)的主要方法。但是,這種方法具有一些缺點(diǎn)。 一個顯著的缺點(diǎn)在于:開發(fā)者必須以一種不同的語言,而非他們當(dāng)前使用的語言(如sql或xpath)來編寫查詢代碼。另一個缺點(diǎn)是,在執(zhí)行某些查詢語言,如sql時,開發(fā)者必須編寫映射代碼將查詢結(jié)果轉(zhuǎn)化為可用的c#業(yè)務(wù)對象。
c#3.0推出一種稱之為語言集成查詢(linq)的新方法。應(yīng)用linq,開發(fā)者可以編寫出能夠搜索任何ienumerable<t>數(shù)據(jù)源的代碼。所以除了應(yīng)用tsql訪問ms sql數(shù)據(jù)庫,應(yīng)用xpath訪問xml文件外,他們還可以應(yīng)用linq。
下面的代碼(列表c)是一個linq查詢的例子,它返回所有ordercount大于10的顧客:
列表c
using system;
using system.query;
using system.collections.generic;
public class sampleclass
{
static void main()
{
list<customer> customers = getcustomers();
//write our query to retrieve customers who have more than
// 10 orders.
ienumerable<customer> queryresult = from customer in customers
where customer.ordercount > 10
orderbycustomer.id
select customer;
}
}
與sql或xpath不同,linq查詢用c#,而非第三方語言編寫。這樣,查詢就不會出現(xiàn)類型問題,開發(fā)者也就沒有必要編寫映射代碼把查詢返回的數(shù)據(jù)轉(zhuǎn)化成c#對象,而由linq api自動處理映射。
基本上,在orm解決方案中,linq對象用途很大。同樣,它的范圍也非常廣泛,有大量msdm信息描述了它的功能。欲了解更多信息,請?jiān)L問linq主頁。