相關文章:.net framework3.5新特性1:Lambda表達式
一、用var定義變量
在C#3.0中提供了一種新的聲明變量的方式,這就是var。 通過這個關鍵字,在聲明變量時就無需指定類型了,變量類型是在初始化時由編譯器確定 的。代碼如下:
var ss="abcd";
MessageBox.Show(ss.GetType().ToString());
上面的代碼將顯示 System.String,從而證明C#編譯器已經將ss編譯成了String變量了。而在輸出ss後,再 輸入“.”後,會看到將String類型變量的相應方法和屬性也列出來了,因此 可以斷定,C#將ss看成了String類型,而不是Object。所以使用var定義變量同時可以擁 有Object和強類型的優點。
不過大家不要將var看成是javascript的var,它們的 區別是,javascript是弱類型的語言,而且javascript中的變量(也包括用var聲明的變 量)可以變換類型,如下面的javascript所示:
var s="abcd";
s=3;
alert(s);
上面的代碼第一次給s賦了一個字符串,而 第二行代碼又給賦了一個整數。這樣的代碼在javascript中沒有任何問題。但在C#3.0中 ,var變量一但被初始化,確定類型後,就無法改變類型了。如下面的代碼是無法編譯通 過的:
var ss="abcd";
ss=44;
綜上所述,在使用var定義變量時有以下四個特點:
1.必須在定義時初始化。也就是必須是var s = “abcd”形式,而不 能是如下形式:
var s;
s=“abcd”;
2.一但初始化完成,就不能再 給變量賦與初始化值類型不同的值了。
3.var要求是局部變量。
4.使用var 定義變量和object不同,它在效率上和使用強類型方式定義變量完全一樣。但筆者建議如 果事先知道變量的類型,盡量使用強類型方式來聲明變量。否則,就會造成由於大量使用 var,而使得開發人員很難斷定某個變量是什麼類型。這樣不利於程序的維護和升級。
雖然var有利有弊,但筆者個人認為,如果將動態語言轉換成C#語言,可以考慮使 用var來定義變量。這是因為動態語言沒有類型,而要將其轉換成強類型的C#語言,就必 須給變量指定個類型,但事先確定類型是很費勁的,不如將其指定成var,再由C#編譯器 去確定變量的具體類型。那麼如果在轉換的過程中,發現動態語言的變量改變了類型,該 怎麼辦呢?這個可以使用第三部分要講的“匿名類”來解決這個問題。
二、初始化
如果一個類有public字段,在建立類的對象實例時可以使用下 面的代碼來初始化這些字段;
public class MyClass
{
public String field1;
public int field2;
public bool field3;
}
MyClass my = new MyClass();
my.field1 = “abcd”;
my.field2 = 44;
my.field3 = true;
在C#3.0中提供了一種更簡便的方法來初始化這些public變量,代碼 如下:
MyClass my=new MyClass
{
field1=“abcd”,
field2=44;
field3=true;
};
上面的代碼的寫法有些象帶 參數的構造方法,但這將不是調用了MyClass的構造方法(因為MyClass並沒有帶三個參數 的構造方法),而只是C#編譯器玩的一個魔術。實際上,上面的代碼在編譯後,仍然和使 用傳統的初始化字段的方法一樣。只是在語法上看起來更簡單(至少不用寫那麼多個my) 。要注意的的,使用這種方法初始化,必須是public的字段(不能是protected、private 或默認修飾符的字段)。
在C#3.0中還改進了對集合類的初始化方式(使其初始化 的方式類似於數組)。但遺憾的是,這種初始化方式只支持用泛型的集合類,也就是說, 只有實現了System.Collections.Generic.ICollection<T>的集合類才可以使用這 種初始化方法。代碼如下:
List<string>myList=new List<string> {"data1","data2","data3"};
foreach (string data in myList)
{
textBox1.AppendText(data);
}
三、匿名類
在C#3.0中提供了一種新的建立類的方法,代碼如下:
var my=new
{
field1="abcd",
field2=12
};
MessageBox.Show(my.field1);
C#編譯器會自動 推斷my是一個有兩個public字段的類的對象實例。也就是說相當於下面的代碼:
public class MyClass
{
public String field1;
public int field2;
}
var my = new MyClass();
my.field1 = "abcd";
my.field2 = 25;
MessageBox.Show(my.field1);
在第一部分講到如果動態語言在給變量賦值的過程中 改變了變量類型,如果將其轉換為強類型語言。當然,一種方法是將變量聲明成object類 型,或是使用匿名類來解決這個問題。代碼如下:
var myVar=new
{
field_string=“abcd”
field_int=12;
};
然後根據當前這個變量所使用的類型來決 定該使用哪個類字段。
四、擴展方法
這個世界上總是存在著很多奇妙的東 西。然而,在這部分所介紹的擴展方法就是其中之一。從字面上看可能讀者很難猜透 “擴展方法”是什麼意思。然而,看了下面的例子,就會感覺到非常的奇妙。
namespace ExtMethod
{
public class Class1
{
public String s = "bill";
}
public class Class2 : Class1
{
}
public static class AnyClassName
{
public static String getName(this Class1 class1)
{
return class1.s + class1.s;
}
}
public partial class Form1 : Form
{
private void button1_Click(object sender, EventArgs e)
{
Class1 c = new Class1();
MessageBox.Show(c.getName());
Class2 c = new Class2();
MessageBox.Show(c.getName());
}
}
}
看到上面的代碼,也許很多人會感到奇怪,在Class1和Class2中並沒有getName方法, 怎麼在調用時出來個getName方法呢?實際上,這就是擴展方法的用法,從本質上說,擴 展方法就是將靜態方法(必須聲明成static)插入到某個類和其子類中(也就是說,在這 些類中可以使用在外部定義的靜態方法)。那麼要往哪個類中插入呢?這就要在定義靜態 方法時指定了。大家可以看看getName方法的第一個參數,使用了this關鍵字,這就表明 這個方法是一個擴展方法,後面的類型就是要插入該方法的類,在本例中是Class1,也就 是說在Class1及其子類中都可以使用getName方法。上面的調用代碼也相當於下面的代碼 :
Class2 c=new Class2();
MessageBox.Show(AnyClassName.getName (c));
但使用c.getName可能會更好一些,而且也降低了對靜態方法所在的 類(AnyClassName)的依賴性。
在使用擴展方法時應注意以下幾點:
1.擴展 方法所在的類名可以是任意合法的類名。
2.擴展方法所在的類必須和使用擴展方 法的代碼在同一個命名空間裡,否則無法編譯通過。
3.在本例中,Class1和 Class2只能聲明成public,因為AnyClassName被聲明為public。如果AnyClassName不加修 飾符,Class1和Class2也可以不加修飾符,當然,也可以被聲明為public。也就是說, Class1和Class2必須有比AnyClassName具有更強的訪問性。如下面代碼所示:
class Class1
{
public String s = "bill";
}
class Class2 : Class1
{
}
static class AnyClassName // 這時如果前面加public是無法編譯通過的。
{
public static String getName(this Class1 class1)
{
return class1.s + class1.s;
}
}
4.如果在Class1或Class2中已經有getName方 法了,那麼Class1或Class2中的getName優先級更高。也就是說,擴展方法是無法覆蓋原 類中的同名(參數名和類型也相同)的方法的。
擴展方法尤其在很多類需要同樣 的方法,而這些類又無法繼承其它類時特別有用。當然,在要對某個類進行擴展,但我們 並沒有源代碼時,擴展方法也可以派上用場。
相關文章
.net framework3.5新特性1:Lambda表達式:
http://www.bianceng.cn/Programming/net/201102/24073.htm
文章來 源:http://www.cnblogs.com/nokiaguy/archive/2008/06/10/1216970.html