欧美色欧美亚洲高清在线观看,国产特黄特色a级在线视频,国产一区视频一区欧美,亚洲成a 人在线观看中文

  1. <ul id="fwlom"></ul>

    <object id="fwlom"></object>

    <span id="fwlom"></span><dfn id="fwlom"></dfn>

      <object id="fwlom"></object>

      C#學(xué)習(xí)心得(五篇材料)

      時(shí)間:2019-05-12 15:15:33下載本文作者:會(huì)員上傳
      簡(jiǎn)介:寫寫幫文庫(kù)小編為你整理了多篇相關(guān)的《C#學(xué)習(xí)心得》,但愿對(duì)你工作學(xué)習(xí)有幫助,當(dāng)然你在寫寫幫文庫(kù)還可以找到更多《C#學(xué)習(xí)心得》。

      第一篇:C#學(xué)習(xí)心得

      C#速成

      一、緒論

      C#是這樣的一種語(yǔ)言,具有C++的特點(diǎn),象Java一樣的編程風(fēng)格, 并且象Basic一樣的快速開(kāi)發(fā)模型。如果你已經(jīng)知道了C++,本文會(huì)在不到一個(gè)小時(shí)的時(shí)間內(nèi)讓你迅速掌握C#的語(yǔ)法。熟悉Java的括會(huì)更好,因?yàn)镴ava的程序結(jié)構(gòu)、打包(Packages)和垃圾收集的概念有助于你更快的了解C#。因此在討論C#的構(gòu)造時(shí),我會(huì)假定你了解C++。

      本文會(huì)討論C#語(yǔ)言的構(gòu)造與特點(diǎn),同時(shí)會(huì)采取簡(jiǎn)潔的和你能理解的方式使用些代碼示例,我們會(huì)盡量讓你能稍微看看這些代碼就能理解這些概念。

      注意:本文不是為C#高手(C# gurus)所寫.這是針對(duì)在C#學(xué)習(xí)上還是初學(xué)者的文章。下面是將要討論的C#問(wèn)題的目錄: 程序結(jié)構(gòu) 命名空間 數(shù)據(jù)類型 變量

      運(yùn)算符和表達(dá)式 枚舉

      語(yǔ)句(Statements)

      類(Classes)和結(jié)構(gòu)(Structs)修飾符(Modifiers)屬性(Properties)接口(Interfaces)方法參數(shù)(Function Parameters)數(shù)組(Arrays)索引器(Indexers)裝箱及拆箱操作 委托(Delegates)繼承和多態(tài)

      下面的內(nèi)容將不會(huì)在被討論之列:

      C++與C#誰(shuí)更通用

      諸如垃圾回收、線程以及文件處理等概念 數(shù)據(jù)的類型轉(zhuǎn)換 異常處理.NET庫(kù)

      二、程序結(jié)構(gòu)

      這一點(diǎn)象C++,C#是一種對(duì)大小寫字母敏感的語(yǔ)言,分號(hào)“;”是語(yǔ)句間的分隔符。與C++不同的是,C#當(dāng)中聲明代碼文件(頭文件)與實(shí)現(xiàn)代碼文件(cpp文件)不是獨(dú)立存在的,所有代碼(類聲明和類實(shí)現(xiàn))都位于一個(gè)擴(kuò)展名為cs的文件內(nèi)。

      讓我們瞧瞧C#當(dāng)中的 Hello world 程序是怎樣的。using System;namespace MyNameSpace { class HelloWorld { static void Main(string[] args){ Console.WriteLine(“Hello World”);} } }

      在C#當(dāng)中的每樣?xùn)|西都被封裝到一個(gè)類中,C#的類又被封裝到一個(gè)命名空間當(dāng)中(就象一個(gè)文件夾中的文件)。類似于 C++,main方法是你的程序的入口點(diǎn)。C++的main函數(shù)調(diào)用名稱是“main”,而C#的main函數(shù)是以大寫字母M為起點(diǎn)的名稱是“Main”。

      沒(méi)有必要把分號(hào)分隔符放在類語(yǔ)句塊或者結(jié)構(gòu)定義語(yǔ)句塊后。這在C++當(dāng)中被要求,但在C#當(dāng)中卻不是。

      三、命名空間

      每一個(gè)類都被包裝進(jìn)一個(gè)命名空間。命名空間的概念與C++的完全相同,但在C#當(dāng)中使用命名空間的頻率較C++還高。你可以使用點(diǎn)限定符(dot qulifier)訪問(wèn)一個(gè)類。在上面的hello world程序當(dāng)中MyNameSpace就是一個(gè)命名空間。

      現(xiàn)在思考這樣的一個(gè)問(wèn)題,你想從某些別的類的命名空間當(dāng)中來(lái)訪問(wèn)HelloWorld這個(gè)類該如何操作。

      這有一個(gè)例子:

      using System;namespace AnotherNameSpace { class AnotherClass { public void Func(){ Console.WriteLine(“Hello World”);} } }

      現(xiàn)在,從你的HelloWorld類里你能象這樣去訪問(wèn)上面的這個(gè)AnotherNameSpace的命名空間: using System;using AnotherNameSpace;// you will add this using statement namespace MyNameSpace { class HelloWorld { static void Main(string[] args){ AnotherClass obj = new AnotherClass();obj.Func();} } }

      在.NET庫(kù)當(dāng)中,System是位于頂層的命名空間,別的命名空間都存在這個(gè)命名空間之下。默認(rèn)狀態(tài)下,存在一個(gè)全局的命名空間,因此一個(gè)在命名空間外定義的類將直接在這個(gè)全局命名空間之下;因此,你能在沒(méi)有任何點(diǎn)限定符的情況下訪問(wèn)這個(gè)類。

      四、變量

      除以下區(qū)別外,C#當(dāng)中的變量幾乎與C++同:

      與C++不同,C#變量被訪問(wèn)之前必須被初始化;否則編譯時(shí)會(huì)報(bào)錯(cuò)。因此,訪問(wèn)一個(gè)未初始化變量是不可能的事。

      C#中你不會(huì)訪問(wèn)到一個(gè)不確定的指針。(譯者注:嚴(yán)格說(shuō)起來(lái)C#已經(jīng)把指針概念異化,限制更嚴(yán)格。所以有些資料上會(huì)說(shuō)C#取消了指針概念)一個(gè)超出數(shù)組邊界的表達(dá)式是不可訪問(wèn)的。

      C#中沒(méi)有全局(整個(gè)Application)的變量或全局函數(shù),全局方式的操作是通過(guò)靜態(tài)函數(shù)和靜態(tài)變量來(lái)實(shí)現(xiàn)的。

      五、數(shù)據(jù)類型

      所有C#數(shù)據(jù)類型都派生自基類Object。這里有兩類數(shù)據(jù)類型: 基本型/內(nèi)置型 用戶自定義型 下面一個(gè)C#內(nèi)置類型列表:

      類型 字節(jié)數(shù) 解釋 byte 1 無(wú)符號(hào)字節(jié)型 sbyte 1 有符號(hào)字節(jié)型 short 2 有符號(hào)短字節(jié)型 ushort 2 無(wú)符號(hào)短字節(jié)型 int 4 有符號(hào)整型 uint 4 無(wú)符號(hào)整型 long 8 有符號(hào)長(zhǎng)整型 ulong 8 無(wú)符號(hào)長(zhǎng)整型 float 4 浮點(diǎn)數(shù) double 8 雙精度數(shù) decimal 8 固定精度數(shù) string unicode字串型 char unicode字符型 bool 真假布爾型

      注意:C#當(dāng)中的類型范圍與C++有所不同;例如,C++的long型是4個(gè)字節(jié),而在C#當(dāng)中是8個(gè)字節(jié)。同樣地,bool型和string型都不同于C++。bool型只接受true和false兩種值。不接受任何整數(shù)類型。

      用戶定義類型包括: 類類型(class)結(jié)構(gòu)類型(struct)接口類型(interface)

      數(shù)據(jù)類型的內(nèi)存分配形式的不同又把它們分成了兩種類型: 值類型(Value Types)

      引用類型(Reference Types)

      值類型:

      值類型數(shù)據(jù)在棧中分配。他們包括:所有基本或內(nèi)置類型(不包括string類型)、結(jié)構(gòu)類型、枚舉類型(enum type)

      引用類型:

      引用類型在堆中分配,當(dāng)它們不再被使用時(shí)將被垃圾收集。它們使用new運(yùn)算符來(lái)創(chuàng)建,對(duì)這些類型而言,不存在C++當(dāng)中的delete操作符,根本不同于C++會(huì)顯式使用delete這個(gè)運(yùn)算符去釋放創(chuàng)建的這個(gè)類型。C#中,通過(guò)垃圾收集器,這些類型會(huì)自動(dòng)被收集處理。引用類型包括:類類型、接口類型、象數(shù)組這樣的集合類型類型、字串類型、枚舉類型 枚舉類型與C++當(dāng)中的概念非常相似。它們都通過(guò)一個(gè)enum關(guān)鍵字來(lái)定義。示例:

      enum Weekdays { Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday }

      類類型與結(jié)構(gòu)類型的比較

      除了在內(nèi)存分配形式上外,類與結(jié)構(gòu)的概念完全與C++相同。類的對(duì)象被分配在堆中,并且通過(guò)new來(lái)創(chuàng)建,結(jié)構(gòu)也是被new創(chuàng)建但卻被分配在棧當(dāng)中。C#當(dāng)中,結(jié)構(gòu)型適于快速訪問(wèn)和擁有少量成員的數(shù)據(jù)類型。如果涉及量較多,你應(yīng)該創(chuàng)建一個(gè)類來(lái)實(shí)現(xiàn)他。

      (譯者注:這與堆和棧內(nèi)存分配結(jié)構(gòu)的特點(diǎn)有關(guān)。簡(jiǎn)而言之,棧是一種順序分配的內(nèi)存;堆是不一定是連續(xù)的內(nèi)存空間。具體內(nèi)容需要大家參閱相關(guān)資料)示例:

      struct Date { int day;int month;int year;}

      class Date { int day;int month;int year;string weekday;string monthName;

      public int GetDay(){ return day;}

      public int GetMonth(){ return month;}

      public int GetYear(){ return year;}

      public void SetDay(int Day){ day = Day;}

      public void SetMonth(int Month){ month = Month;}

      public void SetYear(int Year){ year = Year;}

      public bool IsLeapYear(){ return(year/4 == 0);}

      public void SetDate(int day, int month, int year){

      }...}

      六、屬性

      如果你熟悉C++面象對(duì)象的方式,你就一定有一個(gè)屬性的概念。在上面示例當(dāng)中,以C++的觀點(diǎn)來(lái)看,Data類的屬性就是day、month和year。用C#方式,你可以把它們寫成Get和Set方法。C#提供了一個(gè)更方便、簡(jiǎn)單、直接的方式來(lái)訪問(wèn)屬性。

      因此上面的類可以被寫成:

      using System;class Date { int day;public int Day{ get { return day;}

      set { day = value;} }

      int month;

      public int Month{

      get { return month;}

      set { month = value;} }

      int year;

      public int Year{

      get { return year;}

      set { year = value;} }

      public bool IsLeapYear(int year){ return year%4== 0 ? true: false;}

      public void SetDate(int day, int month, int year){ this.day = day;this.month = month;this.year = year;} }

      你可在這里得到并設(shè)置這些屬性:

      class User {

      public static void Main(){ Date date = new Date();date.Day = 27;date.Month = 6;date.Year = 2003;Console.WriteLine(“Date: {0}/{1}/{2}”, date.Day, date.Month, date.Year);} }

      七、修飾符

      你必須已經(jīng)知道public、private、protected這些常在C++當(dāng)中使用的修飾符。這里我會(huì)討論一些C#引入的新的修飾符。readonly(只讀)

      readonly修飾符僅在類的數(shù)據(jù)成員中使用。正如這名字所提示的,readonly 數(shù)據(jù)成員僅能只讀,它們只能在構(gòu)造函數(shù)或是直接初始化操作下賦值一次。readonly與const數(shù)據(jù)成員不同,const 要求你在聲明中初始化,這是直接進(jìn)行的??聪旅娴氖纠a: class MyClass {

      const int constInt = 100;//直接初始化

      readonly int myInt = 5;//直接初始化

      readonly int myInt2;//譯者注:僅做聲明,未做初始化

      public MyClass(){ myInt2 = 8;//間接的 }

      public Func(){ myInt = 7;//非法操作(譯者注:不得賦值兩次)Console.WriteLine(myInt2.ToString());} }

      sealed(密封)

      密封類不允許任何類繼承,它沒(méi)有派生類。因此,你可以對(duì)你不想被繼承的類使用sealed關(guān)鍵字。

      sealed class CanNotbeTheParent { int a = 5;}

      unsafe(不安全)

      你可使用unsafe修飾符來(lái)定義一個(gè)不安全的上下文。在不安全的上下文里,你能寫些如C++指針這樣的不安全的代碼??聪旅娴氖纠a:

      public unsafe MyFunction(int * pInt, double* pDouble){ int* pAnotherInt = new int;*pAnotherInt = 10;pInt = pAnotherInt;...*pDouble = 8.9;}

      八、interface(接口)

      如果你有COM方面的概念,你會(huì)立亥明白我要談?wù)摰膬?nèi)容。一個(gè)接口就是一個(gè)抽象的基類,這個(gè)基類僅僅包含功能描述,而這些功能的實(shí)現(xiàn)則由子類來(lái)完成。C#中你要用interface關(guān)鍵字來(lái)定義象接口這樣的類。.NET就是基于這樣的接口上的。C#中你不支持C++所允許的類多繼承(譯者注:即一個(gè)派生類可以從兩個(gè)或兩個(gè)以上的父類中派生)。但是多繼承方式可以通過(guò)接口獲得。也就是說(shuō)你的一個(gè)子類可以從多個(gè)接口中派生實(shí)現(xiàn)。interface myDrawing { int originx { get;set;} int originy { get;set;} void Draw(object shape);} class Shape: myDrawing { int OriX;int OriY;public int originx { get{ return OriX;} set{ OriX = value;} } public int originy { get{ return OriY;} set{ OriY = value;} } public void Draw(object shape){...// do something }

      // class's own method public void MoveShape(int newX, int newY){.....} }

      九、Arrays(數(shù)組)

      C#中的數(shù)組比C++的表現(xiàn)更好。數(shù)組被分配在堆中,因此是引用類型。你不可能訪問(wèn)超出一個(gè)數(shù)組邊界的元素。因此,C#會(huì)防止這樣類型的bug。一些輔助方式可以循環(huán)依次訪問(wèn)數(shù)組元素的功能也被提供了,foreach就是這樣的一個(gè)語(yǔ)句。與C++相比,C#在數(shù)組語(yǔ)法上的特點(diǎn)如下: 方括號(hào)被置于數(shù)據(jù)類型之后而不是在變量名之后。創(chuàng)建數(shù)組元素要使用new操作符。

      C#支持一維、多維以及交錯(cuò)數(shù)組(數(shù)組中的數(shù)組)。示例:

      int[] array = new int[10];// 整型一維數(shù)組 for(int i = 0;i < array.Length;i++){ array[i] = i;} int[,] array2 = new int[5,10];// 整型二維數(shù)組 array2[1,2] = 5;int[,] array3 = new int[5,10,5];// 整型的三維數(shù)組 array3[0,2,4] = 9;int[][] arrayOfarray = = new int[2];// 整型交錯(cuò)數(shù)組(數(shù)組中的數(shù)組)arrayOfarray[0] = new int[4];arrayOfarray[0] = new int[] {1,2,15};

      十、索引器

      索引器被用于寫一個(gè)訪問(wèn)集合元素的方法,集合使用“[]”這樣的直接方式,類似于數(shù)組。你所要做的就是列出訪問(wèn)實(shí)例或元素的索引清單。類的屬性帶的是輸入?yún)?shù),而索引器帶的是元素的索引表,除此而外,他們二者的語(yǔ)法相同。示例: 注意:CollectionBase是一個(gè)制作集合的庫(kù)類。List是一個(gè)protected型的CollectionBase成員,儲(chǔ)存著集合清單列表。class Shapes: CollectionBase { public void add(Shape shp){ List.Add(shp);} //indexer public Shape this[int index] { get { return(Shape)List[index];} set { List[index] = value;} } }

      十一、裝箱和拆箱操作(Boxing/Unboxing)

      C#的裝箱思想是全新的。上面提到過(guò)所有的數(shù)據(jù)類型,不論內(nèi)置或用戶自定義,全都從命名空間System的一個(gè)基類object派生出來(lái)。因此把基本的或者原始類型轉(zhuǎn)換成object類型被稱做裝箱,反之,這種方式的逆操作被稱為拆箱。示例: class Test { static void Main(){ int myInt = 12;object obj = myInt;// 裝箱 int myInt2 =(int)obj;// 拆箱 } }

      示例展示了裝箱和拆箱操作。一個(gè)整型值轉(zhuǎn)換成object類型,然后又轉(zhuǎn)換回整型。當(dāng)一個(gè)值類型的變量需要轉(zhuǎn)換成引用類型時(shí),一個(gè)object的箱子會(huì)被分配容納這個(gè)值的空間,這個(gè)值會(huì)被復(fù)制進(jìn)這個(gè)箱子。拆箱與此相反,一個(gè)object箱子中的數(shù)據(jù)被轉(zhuǎn)換成它的原始值類型時(shí),這個(gè)值將被從箱中復(fù)制到適當(dāng)?shù)拇鎯?chǔ)位置。

      十二、方法參數(shù)

      C#中有三種類型的參數(shù):

      值參數(shù)/輸入型參數(shù)

      引用型參數(shù)/輸入輸出型參數(shù) Out參數(shù)

      如果你有COM接口和它的參數(shù)類型的概念,你會(huì)很容易理解C#參數(shù)類型。值參數(shù)/輸入型參數(shù)

      值概念與C++相同。所要傳遞的值會(huì)被復(fù)制到一個(gè)位置上并被傳遞給函數(shù)。示例: SetDay(5);void SetDay(int day){....}

      引用型參數(shù)/輸入輸出參數(shù)

      C#中的引用參數(shù)既不是C++中的指針也不是引用操作符(&)來(lái)傳遞的。C#的引用型參數(shù)減少了出錯(cuò)的可能。引用型參數(shù)也被稱作輸入輸出參數(shù),因?yàn)槟銈鬟f了一個(gè)引用地址,因此你可以從函數(shù)中傳遞一個(gè)輸入值并且可以獲得一個(gè)輸出值。

      你不能把一個(gè)未經(jīng)初始化的引用型參數(shù)傳遞給函數(shù)。C#用ref這個(gè)關(guān)鍵字來(lái)聲明引用型參數(shù)。當(dāng)你傳遞一個(gè)變量給函數(shù)要求的引用參數(shù)時(shí)必須使用一個(gè)ref關(guān)鍵字說(shuō)明。示例:

      int a= 5;FunctionA(ref a);// 要用ref聲明變量,否則你會(huì)得到 // 一個(gè)編譯錯(cuò)誤

      Console.WriteLine(a);// 指向地址的值為20 void FunctionA(ref int Val){ int x= Val;Val = x* 4;}

      Out參數(shù)

      Out型參數(shù)僅僅從函數(shù)當(dāng)中返回一個(gè)值。不要求有輸入值。C#用關(guān)鍵字out來(lái)描聲明這個(gè)參數(shù) 示例:

      int Val;GetNodeValue(Val);bool GetNodeValue(out int Val){ Val = value;return true;}

      可變數(shù)量的參數(shù)和數(shù)組

      數(shù)組在C#當(dāng)中是通過(guò)關(guān)鍵字params來(lái)描述傳遞的。作為數(shù)組類型的變量,你能傳遞任意數(shù)量的元素。從下面示例中你可以理解的更好。示例:

      void Func(params int[] array){ Console.WriteLine(“number of elements {0}”,array.Length);} Func();// prints 0 Func(5);// prints 1 Func(7,9);// prints 2 Func(new int[] {3,8,10});// prints 3 int[] array = new int[8] {1,3,4,5,5,6,7,5};Func(array);// prints 8

      十三、運(yùn)算符和表達(dá)式

      運(yùn)算符和表達(dá)式概念與C++完全相同。但是一些新的有用的運(yùn)算符被填加了進(jìn)來(lái)。我將在這里討論其中的某些部分。

      is 運(yùn)算符

      is 運(yùn)算符被用于檢查操作數(shù)的類型是否相同或者是否可以轉(zhuǎn)換。is 運(yùn)算符在多態(tài)環(huán)境下特別有用。它有兩個(gè)操作數(shù),運(yùn)算結(jié)果是一個(gè)布爾型??催@個(gè)示例: void function(object param){ if(param is ClassA)//do something else if(param is MyStruct)//do something } } as 運(yùn)算符

      as 運(yùn)算符檢查操作數(shù)的類型是否可被轉(zhuǎn)換或者是否相等(這些 as通過(guò) is 運(yùn)算符來(lái)完成。如果結(jié)果是可轉(zhuǎn)換的,則結(jié)果將被轉(zhuǎn)換或者被裝箱,成object(關(guān)于as運(yùn)算符進(jìn)行裝箱成目標(biāo)類型的操作請(qǐng)看前面的裝箱/拆箱操作)。如果不可轉(zhuǎn)換或者裝箱,則返回值是null。瞧一瞧下面的例子我們會(huì)更好地理解這個(gè)概念。Shape shp = new Shape();Vehicle veh = shp as Vehicle;// 結(jié)果是null, 類型不可轉(zhuǎn)換 Circle cir = new Circle();Shape shp = cir;Circle cir2 = shp as Circle;//會(huì)被轉(zhuǎn)換 object[] objects = new object[2];objects[0] = “Aisha”;object[1] = new Shape();string str;for(int i=0;i&< objects.Length;i++){ str = objects[i] as string;if(str == null)Console.WriteLine(“can not be converted”);else Console.WriteLine(“{0}”,str);} 輸出: Aisha can not be converted

      十四、語(yǔ)句

      除了對(duì)某些新增語(yǔ)句和對(duì)某些語(yǔ)句的修改以外,C#語(yǔ)句與C++非常相象。下面是新增的語(yǔ)句: foreach 用于循環(huán)依次訪問(wèn)集合元素,比如象數(shù)組等。示例: foreach(string s in array)Console.WriteLine(s);lock 用于鎖住代碼塊,使線程在臨界爭(zhēng)區(qū)內(nèi),別的線程無(wú)法進(jìn)入鎖定的臨界區(qū)。

      checked/unchecked 用于數(shù)值運(yùn)算中的溢出檢測(cè)。示例:

      int x = Int32.MaxValue;x++;// 溢出檢測(cè) { x++;// 異常

      }

      unchecked { x++;// 溢出} }

      下面的語(yǔ)句在C#當(dāng)中已經(jīng)被修改: Switch 執(zhí)行一個(gè)case語(yǔ)句后,程序流程不允許跳到下一個(gè)相鄰case語(yǔ)句。這在C++當(dāng)中是被允許的。示例:

      int var = 100;switch(var){ case 100: Console.WriteLine(“”);// 沒(méi)有break語(yǔ)句

      case 200: Console.WriteLine(“”);break;}

      C++編譯后的輸出:

      C#下,編譯時(shí)會(huì)報(bào)錯(cuò):

      error CS0163: Control cannot fall through from one case label('case 100:')to another 但是你仍然能做C++類似的事 switch(var){ case 100: case 200: Console.WriteLine(“100 or 200”);break;}

      你也可以常數(shù)變量作為case 的值: 示例:

      const string WeekEnd = “Sunday”;const string WeekDay1 = “Monday”;....string WeekDay = Console.ReadLine();switch(WeekDay){ case WeekEnd: Console.WriteLine(“It's weekend!”);break;case WeekDay1: Console.WriteLine(“It's Monday”);break;}

      十五、委托

      委托讓我們把一個(gè)函數(shù)引用存儲(chǔ)在一個(gè)變量里。C++當(dāng)中,這類似于使用typedef定義的函數(shù)指針,我們通常用存儲(chǔ)一個(gè)函數(shù)指針。

      聲明委托使用的關(guān)鍵字是 delegate。瞧瞧這個(gè)示例,你會(huì)理解什么是委托: 示例:

      delegate int Operation(int val1, int val2);public int Add(int val1, int val2){ return val1 + val2;}

      public int Subtract(int val1, int val2){ return val1-val2;}

      public void Perform(){ Operation Oper;Console.WriteLine(“Enter + or-”);string optor = Console.ReadLine();Console.WriteLine(“Enter 2 operands”);string opnd1 = Console.ReadLine();string opnd2 = Console.ReadLine();int val1 = Convert.ToInt32(opnd1);int val2 = Convert.ToInt32(opnd2);if(optor == “+”)Oper = new Operation(Add);Else Oper = new Operation(Subtract);Console.WriteLine(“ Result = {0}”, Oper(val1, val2));}

      十六、繼承和多態(tài)

      C#僅允許單繼承,多繼承要通過(guò)接口來(lái)實(shí)現(xiàn)。示例:

      class Parent { } class Child : Parent { }

      十七、虛擬方法

      除了在子類中實(shí)現(xiàn)虛擬方法采用override關(guān)鍵字外,虛擬方法實(shí)現(xiàn)多態(tài)的概念C#與C++相同。父類使用相同的virtual關(guān)鍵字。從重載虛擬方法的每個(gè)類都要使用override關(guān)鍵字。class Shape { public virtual void Draw(){ Console.WriteLine(“Shape.Draw”);} }

      class Rectangle : Shape { public override void Draw(){ Console.WriteLine(“Rectangle.Draw”);} }

      class Square : Rectangle { public override void Draw(){ Console.WriteLine(“Square.Draw”);} }

      class MainClass { static void Main(string[] args){ Shape[] shp = new Shape[3];Rectangle rect = new Rectangle();shp[0] = new Shape();shp[1] = rect;shp[2] = new Square();shp[0].Draw();shp[1].Draw();shp[2].Draw();} }

      輸出t: Shape.Draw Rectangle.Draw Square.Draw

      十八、使用“new”來(lái)隱藏父方法

      你可以定義一個(gè)子類成一個(gè)新方法版本,隱藏基類當(dāng)中的那個(gè)版本。使用new關(guān)鍵字就可以定義一個(gè)新版本。思考下面的示例,它是上面示例的修改后的版本。注意當(dāng)我用Rectangle類中的new關(guān)鍵字代替override關(guān)鍵字時(shí)示例的輸出情況。

      class Shape { public virtual void Draw(){ Console.WriteLine(“Shape.Draw”);} }

      class Rectangle : Shape { public new void Draw(){ Console.WriteLine(“Rectangle.Draw”);} } class Square : Rectangle { //沒(méi)在這里讓你重載 public new void Draw(){ Console.WriteLine(“Square.Draw”);} } class MainClass { static void Main(string[] args){ Console.WriteLine(“Using Polymorphism:”);Shape[] shp = new Shape[3];Rectangle rect = new Rectangle();shp[0] = new Shape();shp[1] = rect;shp[2] = new Square();shp[0].Draw();shp[1].Draw();shp[2].Draw();Console.WriteLine(“Using without Polymorphism:”);rect.Draw();Square sqr = new Square();sqr.Draw();} } 輸出: Using Polymorphism Shape.Draw Shape.Draw Shape.Draw Using without Polymorphism: Rectangle.Draw Square.Draw 這里的多態(tài)性不會(huì)把Rectangle類的Draw方法當(dāng)做Shape的Draw方法多態(tài)性的一種表現(xiàn)。相反,它會(huì)認(rèn)為這是一種不同的方法。因此,為了避免父類與子類間的命名沖突,我們使用了new修飾符。注意:你不能使用同一類下面一種方法的兩個(gè)版本,即一個(gè)是用new修飾符的版本,另一個(gè)是用override或virtual修飾符的版本。正象上面示例所說(shuō)明的,我不能再在擁有virtual或override方法的Rectangle類中添加另一個(gè)命名為Draw的方法。同樣地,在Square類中,我也不能重載Square類的虛擬的Draw方法。

      十九、調(diào)用基類成員

      如果子類與基類有同名的數(shù)據(jù)成員,為避免命名沖突,訪問(wèn)基類數(shù)據(jù)成員和函要使用一個(gè)關(guān)鍵字base。在下面的示例中我們來(lái)看看如何調(diào)用基類的構(gòu)造函數(shù)以及如何使用數(shù)據(jù)成員。public Child(int val):base(val){ myVar = 5;base.myVar;}

      或者

      public Child(int val){ base(val);myVar = 5;base.myVar;}

      文學(xué)の音聲図書(shū)館[轉(zhuǎn)貼]

      みなさん: こんにちは。私がつくった「文學(xué)の音聲図書(shū)館」をご覧下さい。みなさまの聴力に役立つかもしれません。どうぞ。

      http://作家辭典http://horagai.com/歌舞伎文庫(kù)http://http://日語(yǔ)教材 http://seki.nease.net/yufa.htm 語(yǔ)法網(wǎng)站======================================外來(lái)語(yǔ)從此不再可怕http://[align=right][color=#000066][此貼子已經(jīng)被作者于2005-1-27 20:18:53編輯過(guò)][/color][/align]

      第二篇:C#學(xué)習(xí)心得

      集合聲明:類B可以換成任意object對(duì)象

      1、CollectionBase

      類A繼承CollectionBase類,通過(guò)CollectionBase的成員List實(shí)現(xiàn)類A的Add(類

      B)、Remove(類B)和RemoveAt(類B)方法:

      publicvoidAdd(類B newB)

      {List.Add(newB);}

      publicvoidRemove(類B newB)

      {List.Remove(newB);}

      publicvoidRemoveAt(int index)

      {List.RemoveAt(index);}

      在類A中建立索引可以按類似數(shù)組的方法訪問(wèn)。

      public 類B this[int index]

      {get{return(類B)List[index];}

      set{List[index]=value;}

      }

      利用CollectionBase的成員InnerList(ArrayList對(duì)象)實(shí)現(xiàn)類A的Contains()方法:

      publicboolContains(類B newB)

      {

      returnInnerList.Contains(newB);

      }

      注意:InnerList是ArrayList類實(shí)例,其Contains方法通過(guò)調(diào)用Object.Equals確定相等性,Equals默認(rèn)實(shí)現(xiàn)僅支持引用相等。對(duì)于引用類型,相等定義為對(duì)象相等,即這些引用是否引用同一對(duì)象。對(duì)于值類型,相等定義為按位相等。

      可以在類B中重寫Object.Equals方法和GetHashCode()方法。publicoverrideboolEquals(objectobj)

      {//Check for null and compare run-time types.if(obj == null || GetType()!= obj.GetType())returnfalse;

      B b =(B)obj;

      return(比較邏輯);

      }

      publicoverrideintGetHashCode(){??}

      2、DictionaryBase

      類A繼承DictionaryBase類,通過(guò)DictionaryBase的成員

      Dictionary(IDictionary類型的接口),實(shí)現(xiàn)類A的 Add(object key,類B)和Remove(object key,類B)方法:

      publicvoidAdd(object key,類B newB)

      {Dictionary.Add(key,newB);}

      publicvoidRemove(object key,類B newB)

      {Dictionary.Remove(key,newB);}

      在類A中建立索引可以按類似數(shù)組的方法訪問(wèn)。

      public 類B this[object index]

      {get{return(類B)Dictionary[index];}

      set{Dictionary[index]=value;}

      }

      利用DictionaryBase的接口成員Dictionary實(shí)現(xiàn)類A的Contains()方法: publicboolContains(object key)

      {

      returnDictionary.Contains(key);

      }

      3、迭代器

      對(duì)于繼承CollectionBase類的A,使用

      foreach(BsourceBin類A對(duì)象){}

      對(duì)于繼承DictionaryBase類的A,使用

      foreach(DictionaryEntrysourceBin類A對(duì)象){source.Value.}

      對(duì)于類迭代,使用方法GetEnumerator(),返回類型是IEnumerator;類成員迭代使用IEnumerable(),返回類型是IEnumerable;

      例如繼承DictionaryBase類的A的迭代器,public new IEnumeratorGetEnumerator()

      {foreach(object b in Dictionary.Values)

      yield return(B)b;

      }

      以后使用foreach循環(huán)時(shí),可按照類似繼承CollectionBase類的的方式使用。

      4、淺度復(fù)制與深度復(fù)制

      淺度復(fù)制:簡(jiǎn)單地按照成員復(fù)制對(duì)象可以通過(guò)派生于System.Object的MemberwiseClone()方法來(lái)完成,這是一個(gè)受保護(hù)的方法,但是很容易在對(duì)象上定義一個(gè)調(diào)用該方法的公共方法例如GetCopy()。這個(gè)方法的復(fù)制功能成為淺復(fù)制。淺拷貝是對(duì)引用類型拷貝地址,對(duì)值類型直接進(jìn)行拷貝,但是string類例外,因?yàn)閟tring是readonly的,當(dāng)改變string類型的數(shù)據(jù)值時(shí),將重新分配了內(nèi)存地址。數(shù)組、類也是淺度復(fù)制,而結(jié)構(gòu)體、數(shù)值型、枚舉是深度復(fù)制。

      深度復(fù)制:需要深度復(fù)制的類A添加ICloneable接口,實(shí)現(xiàn)該接口的Clone()方法。

      public object Clone()

      {A newA=new A();

      object []arr=new object[維度];//object 可以是數(shù)值類型,string //不能使用newA.arr=arr;因?yàn)橥ㄟ^(guò)數(shù)組名賦值引用同一地址,是淺度復(fù)制 arr.CopyTo(newA.arr,0);

      returnnewA;}

      假設(shè)類A中有成員對(duì)象類B實(shí)例myB,則在類B定義中也要實(shí)現(xiàn)ICloneable的Clone()方法,class B:ICloneable

      {

      public object Clone(){??}

      }

      然后在類A的Clone方法中,newA.myB=myB.Clone();

      比較

      1、is運(yùn)算符

      檢查對(duì)象是否是給定類型或者是否可以轉(zhuǎn)換為給定類型,是則返回true。 is

      如果type是類類型,operand也是該類型,或繼承該類型、封箱到該類型,為true 如果type是接口類型,operand也是該類型,或?qū)崿F(xiàn)該接口的類型,為true 如果type是值類型,operand也是該類型,或拆箱到該類型,為true2、運(yùn)算符重載

      public static 返回類型 operator 需重載的運(yùn)算符(參數(shù)??){}

      注意不能重載賦值運(yùn)算符,&&和||運(yùn)算符,但可重載&和|;有些運(yùn)算符需成對(duì)重載,如“<”和“>”

      3、IComparable接口

      類A實(shí)現(xiàn)IComparable接口的方法intCompareTo(objectobj)后,利用成員為類A的實(shí)例的ArrayList或Array類可以調(diào)用Sort()方法,按CompareTo(objectobj)的方法排序。

      4、IComparer接口

      類A實(shí)現(xiàn)IComparer接口的方法intCompare(objectx, objecty)后,利用ArrayList或Array類可以調(diào)用Sort(IA)方法(IComparer IA=new A()),按

      Compare(,)方法排序。注意ArrayList或Array類的實(shí)例不一定是類A。也可以在類A中定義一個(gè)公用動(dòng)態(tài)接口成員IComparer ID,這樣可以直接調(diào)用Sort(ID)。另外,在Compare方法中可以調(diào)用Comparer.Default.Compare(,)方法,實(shí)現(xiàn)特定的關(guān)鍵字排序。Default是Compare類的動(dòng)態(tài)實(shí)例。

      轉(zhuǎn)換

      1、隱式和顯示轉(zhuǎn)換

      在沒(méi)有繼承關(guān)系,沒(méi)有共享接口的類型之間轉(zhuǎn)換時(shí),必須定義類型之間的隱式和顯示轉(zhuǎn)換。public classA

      {??

      //定義A到B的隱式轉(zhuǎn)換

      public staticimplicit operatorzhuanB(Aa){?? return }

      }

      public classB

      {??

      //定義B到A的顯式轉(zhuǎn)換

      public staticexplicit operatorzhuanA(Bb){??return }

      }

      2、as運(yùn)算符

      把類型轉(zhuǎn)換為給定類型。

      is

      operand類型是type類型,或可以隱式轉(zhuǎn)換為type類型,或封箱到type類型 如果不能轉(zhuǎn)換,則表達(dá)式的結(jié)果是null

      異常處理

      Exception:所有異常對(duì)象的基類。

      SystemException:運(yùn)行時(shí)產(chǎn)生的所有錯(cuò)誤的基類。

      IndexOutOfRangeException:當(dāng)一個(gè)數(shù)組的下標(biāo)超出范圍時(shí)運(yùn)行時(shí)引發(fā)。NullReferenceException:當(dāng)一個(gè)空對(duì)象被引用時(shí)運(yùn)行時(shí)引發(fā)。

      InvalidOperationException:當(dāng)對(duì)方法的調(diào)用對(duì)對(duì)象的當(dāng)前狀態(tài)無(wú)效時(shí),由某些方法引發(fā)。

      ArgumentException:所有參數(shù)異常的基類。

      ArgumentNullException:在參數(shù)為空(不允許)的情況下,由方法引發(fā)。ArgumentOutOfRangeException:當(dāng)參數(shù)不在一個(gè)給定范圍之內(nèi)時(shí),由方法引發(fā)。

      InteropException:目標(biāo)在或發(fā)生在CLR外面環(huán)境中的異常的基類。ComException:包含COM類的HRESULT信息的異常。

      SEHException:封裝Win32結(jié)構(gòu)異常處理信息的異常。

      SqlException:封裝了SQL操作異常。

      常見(jiàn)具體的異常對(duì)象:

      ArgumentNullException一個(gè)空參數(shù)傳遞給方法,該方法不能接受該參數(shù)ArgumentOutOfRangeException參數(shù)值超出范圍

      ArithmeticException出現(xiàn)算術(shù)上溢或者下溢

      ArrayTypeMismatchException試圖在數(shù)組中存儲(chǔ)錯(cuò)誤類型的對(duì)象

      BadImageFormatException圖形的格式錯(cuò)誤

      DivideByZeroException除零異常

      DllNotFoundException找不到引用的DLL

      FormatException參數(shù)格式錯(cuò)誤

      IndexOutOfRangeException數(shù)組索引超出范圍

      InvalidCastException使用無(wú)效的類

      InvalidOperationException方法的調(diào)用時(shí)間錯(cuò)誤

      NotSupportedException調(diào)用的方法在類中沒(méi)有實(shí)現(xiàn)

      NullReferenceException試圖使用一個(gè)未分配的引用OutOfMemoryException內(nèi)存空間不夠

      StackOverflowException堆棧溢出

      第三篇:C#面向?qū)ο髮W(xué)習(xí)心得

      一、封裝

      這是一種隱藏信息的特性。拿本節(jié)引例來(lái)說(shuō),類CalculateDate 將數(shù)據(jù)結(jié)構(gòu)與算法隱藏在類的內(nèi)部,外界使用者無(wú)需知道具體技術(shù)實(shí)現(xiàn)細(xì)節(jié)即可使用此類。封裝這一特性不僅大大提高了代碼的易用性,而且還使得類的開(kāi)發(fā)者可以方便地更換新的算法,這種變化不會(huì)影響使用類的外部代碼??梢杂靡韵鹿秸故绢惖姆庋b特性:封裝的類=數(shù)據(jù)+對(duì)此數(shù)據(jù)所進(jìn)行的操作(即算法)。通俗地說(shuō),封裝就是:包起外界不必需要知道的東西,只向外界展露可供展示的東西。在面向?qū)ο罄碚撝校庋b這個(gè)概念擁有更為寬廣的含義。小到一個(gè)簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu),大到一個(gè)完整的軟件子系統(tǒng),靜態(tài)的如某軟件系統(tǒng)要收集數(shù)據(jù)信息項(xiàng),動(dòng)態(tài)的如某個(gè)工作處理流程,都可以封裝到一個(gè)類中。具備這種“封裝”的意識(shí),是掌握面向?qū)ο蠓治雠c設(shè)計(jì)技巧的關(guān)鍵。

      二、繼承

      繼承是面向?qū)ο缶幊讨幸粋€(gè)非常重要的特性,它也是另一個(gè)重要特性——多態(tài)的基礎(chǔ)。現(xiàn)實(shí)生活中的事物都?xì)w屬于一定的類別。在一些書(shū)中,將父類稱為超類(super class)?!袄^承”關(guān)系有時(shí)又稱為“派生”關(guān)系,“B 繼承自A”,可以說(shuō)為“B 派生自A”,或反過(guò)來(lái)說(shuō),“A 派生出B”。父類與子類之間擁有以下兩個(gè)基本特性:

      (1)是一種(IS-A)關(guān)系:子類是父類的一種特例。

      (2)擴(kuò)充(Extends)關(guān)系:子類擁有父類所沒(méi)有的功能。

      1.類成員的訪問(wèn)權(quán)限

      面向?qū)ο缶幊痰囊淮筇攸c(diǎn)就是可以控制類成員的可訪問(wèn)性。當(dāng)前主流的面向?qū)ο笳Z(yǔ)言都擁有以下三種基本的可訪問(wèn)性:

      (1)公有 public 訪問(wèn)不受限制。

      (2)私有 private 只有類自身成員可以訪問(wèn)。

      (3)保護(hù) protected 子類可以訪問(wèn),其他類無(wú)法訪問(wèn)。

      由此可見(jiàn),可以通過(guò)子類對(duì)象訪問(wèn)其父類的所有公有成員,事實(shí)上,外界根本分不清楚對(duì)象的哪些公有成員來(lái)自父類,哪些公有成員來(lái)自子類自身。小結(jié)一下繼承條件下的類成員訪問(wèn)權(quán)限:

      (1)所有不必讓外人知道的東西都是私有的。

      (2)所有需要向外提供的服務(wù)都是公有的。

      (3)所有的“祖?zhèn)鹘^招”,“秘不外傳”的都是保護(hù)的。

      C#中還有一種可訪問(wèn)性,就是由關(guān)鍵字internal 所確定的“內(nèi)部”訪問(wèn)性。internal 有點(diǎn)像public,外界類也可以直接訪問(wèn)聲明為internal 的類或類的成員,但這只局限于同一個(gè)程序集內(nèi)部。

      讀者可以簡(jiǎn)單地將程序集理解為一個(gè)獨(dú)立的DLL 或EXE 文件。一個(gè)DLL 或EXE 文件中可以有多個(gè)類,如果某個(gè)類可被同一程序集中的類訪問(wèn),但其他程序集中的類不能訪問(wèn)它,則稱此類具有internal 訪問(wèn)性。internal 是C#的默認(rèn)可訪問(wèn)性,這就是說(shuō),如果某個(gè)類沒(méi)有任何可訪問(wèn)性關(guān)鍵字在它前面,則它就是internal 的。

      2.子類父類變量的相互賦值

      子類對(duì)象可以被當(dāng)成基類對(duì)象使用。這是因?yàn)樽宇悓?duì)象本就是一種(IS_A)父類對(duì)象,因此,以下代碼是合法的:

      Parent p;

      Son c = new Son();

      p = c;

      然而,反過(guò)來(lái)就不可以,父類對(duì)象變量不可以直接賦值給子類變量。如果確信父類變量中所引用的對(duì)象的確是子類類型,則可以通過(guò)類型強(qiáng)制轉(zhuǎn)換進(jìn)行賦值,其語(yǔ)法格式為: 子類對(duì)象變量=(子類名稱)基類對(duì)象變量;

      子類對(duì)象變量=基類對(duì)象變量 as 子類名稱;

      3.方法重載、隱藏與虛方法調(diào)用

      由于子類對(duì)象同時(shí)匯集了父類和子類的所有公共方法,而C#并未對(duì)子類和父類的方法名稱進(jìn)行過(guò)多限制,因此,一個(gè)問(wèn)題出現(xiàn)了:如果子類中某個(gè)方法與父類方法的簽名一樣(即方法名和方法參數(shù)都一樣),那當(dāng)通過(guò)子類對(duì)象訪問(wèn)此方法時(shí),訪問(wèn)的是子類還是父類所定義的方法?讓我們先從子類方法與父類方法之間的關(guān)系說(shuō)起??偟膩?lái)說(shuō),子類方法與父類方法之間的關(guān)系可以概括為以下三種:

      (1)擴(kuò)充(Extend):子類方法,父類沒(méi)有;

      (2)重載(Overload):子類有父類的同名函數(shù),但參數(shù)類型或數(shù)目不一樣;

      (3)完全相同:子類方法與父類方法從方法名稱到參數(shù)類型完全一樣。

      當(dāng)子類與父類擁有完全一樣的方法時(shí),稱“子類隱藏了父類的同名方法,當(dāng)分別位于父類和子類的兩個(gè)方法完全一樣時(shí),調(diào)用哪個(gè)方法由對(duì)象變量的類型決定。“new”關(guān)鍵字明確告訴C#編譯器,子類隱藏父類的同名方法,提供自己的新版本。如果子類隱藏了父類的同名方法,要在子類方法的實(shí)現(xiàn)代碼中調(diào)用父類被隱藏的同名方法時(shí)要使用base 關(guān)鍵字。如果子類隱藏了父類的同名方法,不進(jìn)行強(qiáng)制轉(zhuǎn)換,就無(wú)法通過(guò)父類變量直接調(diào)用子類的同名方法,哪怕父類變量引用的是子類對(duì)象。這是不太合理的。我們希望每個(gè)對(duì)象都只干自己職責(zé)之內(nèi)的事,即如果父類變量引用的是子類對(duì)象,則調(diào)用的就是子類定義的方法,而如果父類變量引用的就是父類對(duì)象,則調(diào)用的是父類定義的方法。這就是說(shuō),希望每個(gè)對(duì)象都“各人自掃門前雪,莫管他人瓦上霜”。為達(dá)到這個(gè)目的,可以在父類同名方法前加關(guān)鍵字virtual,表明這是一個(gè)虛方法,子類可以重寫此方法:即在子類同名方法前加關(guān)鍵字override,表明對(duì)父類同名方法進(jìn)行了重寫。所以,將父類方法定義為虛方法,子類重寫同名方法之后,通過(guò)父類變量調(diào)用此方法,到底是調(diào)用父類還是子類的,由父類變量引用的真實(shí)對(duì)象類型決定,而與父類變量無(wú)關(guān)!很明顯,“虛方法調(diào)用”特性可以讓我們寫出非常靈活的代碼,大大減少由于系統(tǒng)功能

      擴(kuò)充和改變所帶來(lái)的大量代碼修改工作量。由此給出結(jié)論:面向?qū)ο笳Z(yǔ)言擁有的“虛方法調(diào)用”特性,使我們可以只用同樣的一個(gè)語(yǔ)句,在運(yùn)行時(shí)根據(jù)對(duì)象類型而執(zhí)行不同的操作。

      三、抽象

      1.抽象類與抽象方法

      在一個(gè)類前面加上“abstract”關(guān)鍵字,此類就成為了抽象類。對(duì)應(yīng)地,一個(gè)方法類前面加上“abstract”關(guān)鍵字,此方法就成為了抽象方法。注意抽象方法不能有實(shí)現(xiàn)代碼,在函數(shù)名后直接跟一個(gè)分號(hào)。抽象類專用于派生出子類,子類必須實(shí)現(xiàn)抽象類所聲明的抽象方法,否則,子類仍是抽象類。抽象類一般用于表達(dá)一種比較抽象的事物,而抽象方法則說(shuō)明此抽象類應(yīng)該具有的某種性質(zhì),從同一抽象類中繼承的子類擁有相同的方法(即抽象類所定義的抽象方法),但這些方法的具體代碼每個(gè)類都可以不一樣。抽象類不能創(chuàng)建對(duì)象,一般用

      它來(lái)引用子類對(duì)象。一個(gè)抽象類中可以包含非抽象的方法和字段。因此:包含抽象方法的類一定是抽象類,但抽象類中的方法不一定是抽象方法。除了方法可以是抽象的之外,屬性也可以是抽象的。

      2.接口

      接口可以看成是一種“純”的抽象類,它的所有方法都是抽象方法。抽象類定義了對(duì)象所屬的類別,而接口實(shí)際上定義了一種對(duì)象應(yīng)具有的行為特性。某個(gè)類可以實(shí)現(xiàn)多個(gè)接口,當(dāng)創(chuàng)建一個(gè)此類的對(duì)象之后,通過(guò)引用這個(gè)對(duì)象的對(duì)象變量可以訪問(wèn)其所有的公有方法(包括自身的公有方法以及由接口定義的公有方法以)。在這種情況下,根本分不清哪些方法是由接口定義的,哪些是由類自己定義的。C#提供了一種“顯式接口”實(shí)現(xiàn)機(jī)制,可以區(qū)分開(kāi)這兩種情況。由此得到一個(gè)結(jié)論:如果一個(gè)類顯式實(shí)現(xiàn)某個(gè)接口,則只能以此接口類型的變量為媒介調(diào)用此接口所定義的方法,而不允許通過(guò)類的對(duì)象變量直接調(diào)用?;蛘哌@樣說(shuō):被顯式實(shí)現(xiàn)的接口方法只能通過(guò)接口實(shí)例訪問(wèn),而不能通過(guò)類實(shí)例直接訪問(wèn)。

      四、多態(tài)

      方法重載屬于多態(tài)的一種,兩個(gè)構(gòu)成重載關(guān)系的函數(shù)必須滿足幾個(gè)條件:函數(shù)名相同、參數(shù)類型不同,或參數(shù)個(gè)數(shù)不同。具體調(diào)用哪個(gè)方法要看參數(shù),需要注意的是,方法返回值類型的不同不是方法重載的判斷條件。多態(tài)編程的基本原理是:使用基類或接口變量編程。在多態(tài)編程中,基類一般都是抽象基類,其中擁有一個(gè)或多個(gè)抽象方法,各個(gè)子類可以根據(jù)需要重寫這些方法?;蛘呤褂媒涌?,每個(gè)接口都規(guī)定了一個(gè)或多個(gè)抽象方法,實(shí)現(xiàn)接口的類根據(jù)需要實(shí)現(xiàn)這些方法。因此,多態(tài)的實(shí)現(xiàn)分為兩大基本類別:繼承多態(tài)和接口多態(tài)。

      1.接口多態(tài)與繼承多態(tài)

      接口多態(tài)與繼承多態(tài)其編程方式與作用都是類似的。但由于一個(gè)類可以實(shí)現(xiàn)多個(gè)接口,所以,接口多態(tài)較繼承多態(tài)更靈活,因而在編程中也用得更廣。多態(tài)是面向?qū)ο蠹夹g(shù)中最精華的部分之一。大量的精巧軟件設(shè)計(jì)方案都建立在對(duì)多態(tài)特性的巧妙應(yīng)用上。在編程中應(yīng)用多態(tài),可以將其簡(jiǎn)化為兩句:應(yīng)用繼承實(shí)現(xiàn)對(duì)象的統(tǒng)一管理;應(yīng)用接口定義對(duì)象的行為特性。對(duì)比傳統(tǒng)的不使用多態(tài)的編程方式,使用多態(tài)的好處是:當(dāng)要修改程序并擴(kuò)充系統(tǒng)時(shí),需要修改的地方較少,對(duì)其他部分代碼的影響較小。

      五、類與對(duì)象

      類是面向?qū)ο缶幊痰幕締卧?,與使用C語(yǔ)言等結(jié)構(gòu)化編程語(yǔ)言不一樣,使用C#編程,所有的程序代碼幾乎都放在類中,不存在獨(dú)立于類之外的函數(shù)。一個(gè)類可以包含兩種成員:靜態(tài)成員和實(shí)例成員,靜態(tài)成員是供類的所有對(duì)象所共享的,而實(shí)例成員只供某一個(gè)對(duì)象所有。實(shí)例成員與靜態(tài)成員的訪問(wèn)規(guī)則:位于同一類中的實(shí)例方法可直接相互調(diào)用;類的字段(包括實(shí)例字段和靜態(tài)字段)可以被同一類中的所有實(shí)例方法直接訪問(wèn);類中的靜態(tài)方法只能直接訪問(wèn)類靜態(tài)字段。

      類中包括:方法和字段,屬性是一種特殊的字段,它可以保證數(shù)據(jù)的合法性,方法和字段這兩個(gè)概念是面向?qū)ο罄碚摰男g(shù)語(yǔ),是通用于各種面向?qū)ο笳Z(yǔ)言的。字段(Field)代表了類中的數(shù)據(jù),在類的所有方法之外定義一個(gè)變量即定義了一個(gè)字段。在變量之前可以加上public、private 和protected 表示字段的訪問(wèn)權(quán)限。方法(function)功能代碼的集合,在程序開(kāi)發(fā)過(guò)程中,經(jīng)常發(fā)現(xiàn)多處需要實(shí)現(xiàn)或調(diào)用某一個(gè)公用功能,這些功能的實(shí)現(xiàn)都需要書(shū)

      寫若干行代碼。如果在調(diào)用此功能的地方重復(fù)書(shū)寫這些功能代碼,將會(huì)使整個(gè)程序中代碼大量重復(fù),會(huì)增大開(kāi)發(fā)工作量,增加代碼維護(hù)的難度。為了解決代碼重復(fù)的問(wèn)題,絕大多數(shù)程序設(shè)計(jì)語(yǔ)言都將完成某一公用功能的多個(gè)語(yǔ)句組合在一起,起一個(gè)名字用于代表這些語(yǔ)句的全體,這樣的代碼塊被稱為“函數(shù)(function)”。引入“函數(shù)”概念之后,程序中凡需要調(diào)用此公用功能的地方都可以只寫出函數(shù)名,此名字就代表了函數(shù)中所包含的所有代碼,這樣一來(lái),就不再需要在多個(gè)地方重復(fù)書(shū)寫這些功能代碼。

      對(duì)象是以類為模板創(chuàng)建出來(lái)的。類與對(duì)象之間是一對(duì)多的關(guān)系。在C#中,使用new 關(guān)鍵字創(chuàng)建對(duì)象。在程序中“活躍”的是對(duì)象而不是類。在面向?qū)ο箢I(lǐng)域,對(duì)象有時(shí)又被稱為是“類的實(shí)例”,“對(duì)象”與“類的實(shí)例”這兩個(gè)概念是等同的。

      六、值類型與引用類型

      1.值類型

      值類型變量與引用類型變量的內(nèi)存分配模型也不一樣。每個(gè)正在運(yùn)行的程序都對(duì)應(yīng)著一個(gè)進(jìn)程(process),在一個(gè)進(jìn)程內(nèi)部,可以有一個(gè)或多個(gè)線程(thread),每個(gè)線程都擁有一塊“自留地”,稱為“線程堆?!?,大小為1M,用于保存自身的一些數(shù)據(jù),比如函數(shù)中定義的局部變量、函數(shù)調(diào)用時(shí)傳送的參數(shù)值等,這部分內(nèi)存區(qū)域的分配與回收不需要程序員干涉。所有值類型的變量都是在線程堆棧中分配的。值類型共有三種:簡(jiǎn)單類型、枚舉類型和結(jié)構(gòu)類型。

      2.引用類型

      另一塊內(nèi)存區(qū)域稱為“堆(heap)”,在.NET 這種托管環(huán)境下,堆由CLR 進(jìn)行管理,所以又稱為“托管堆(managed heap)”。用new 關(guān)鍵字創(chuàng)建的類的對(duì)象時(shí),分配給對(duì)象的內(nèi)存單元就位于托管堆中。在程序中我們可以隨意地使用new 關(guān)鍵字創(chuàng)建多個(gè)對(duì)象,因此,托管堆中的內(nèi)存資源是可以動(dòng)態(tài)申請(qǐng)并使用的,當(dāng)然用完了必須歸還。打個(gè)比方更易理解:托管堆相當(dāng)于一個(gè)旅館,其中的房間相當(dāng)于托管堆中所擁有的內(nèi)存單元。當(dāng)程序員用new 方法創(chuàng)建對(duì)象時(shí),相當(dāng)于游客向旅館預(yù)訂房間,旅館管理員會(huì)先看一下有沒(méi)有合適的空房間,有的話,就可以將此房間提供給游客住宿。當(dāng)游客旅途結(jié)束,要辦理退房手續(xù),房間又可以為其他旅客提供服務(wù)了。引用類型共有四種:類類型、接口類型、數(shù)組類型和委托類型。所有引用類型變量所引用的對(duì)象,其內(nèi)存都是在托管堆中分配的。嚴(yán)格地說(shuō),我們常說(shuō)的“對(duì)象變量”其實(shí)是類類型的引用變量。但在實(shí)際中人們經(jīng)常將引用類型的變量簡(jiǎn)稱為“對(duì)象變量”,用它來(lái)指代所有四種類型的引用變量。

      七、命名空間與類庫(kù)

      1.命名空間

      在使用面向?qū)ο蠹夹g(shù)開(kāi)發(fā)的現(xiàn)代軟件系統(tǒng)中,經(jīng)常擁有數(shù)百甚至上千個(gè)類,為了方便地管理這些類,面向?qū)ο蠹夹g(shù)引入了“命名空間(namespace)”的概念。命名空間可以看成是類的“容器”,它可以包含多個(gè)類。.NET Framework 使用命名空間來(lái)管理所有的類。如果把類比喻成書(shū)的話,則命名空間類似于放書(shū)的書(shū)架,書(shū)放在書(shū)架上,類放在命名空間里。當(dāng)我們?nèi)D書(shū)館查找一本書(shū)時(shí),需要指定這本書(shū)的編號(hào),編號(hào)往往規(guī)定了書(shū)放在哪個(gè)書(shū)庫(kù)的哪個(gè)書(shū)架上,通過(guò)逐漸縮小的范圍:圖書(shū)館->書(shū)庫(kù)->書(shū)架,最終可以在某個(gè)書(shū)架中找到這本書(shū)。類似地,可以采用圖書(shū)館保存圖書(shū)類似的方法來(lái)管理類,通過(guò)逐漸縮小的范圍:最大的命名空間->子命名空間->孫命名空間??,最終找到一個(gè)類。

      2.類庫(kù)

      為了提高軟件開(kāi)發(fā)的效率,人們?cè)谡麄€(gè)軟件開(kāi)發(fā)過(guò)程中大量應(yīng)用了軟件工程的模塊化原則,將可以在多個(gè)項(xiàng)目中使用的代碼封裝為可重用的軟件模塊,其于這些可復(fù)用的軟件模塊,再開(kāi)發(fā)新項(xiàng)目就成為“重用已有模塊,再開(kāi)發(fā)部分新模塊,最后將新舊模塊組裝起來(lái)”的過(guò)程。整個(gè)軟件開(kāi)發(fā)過(guò)程類似于現(xiàn)代工業(yè)的生產(chǎn)流水線,生產(chǎn)線上的每個(gè)環(huán)節(jié)都由特定的人員負(fù)責(zé),整個(gè)生產(chǎn)線上的工作人員既分工明確又相互合作,大大地提高了生產(chǎn)效率。在組件化開(kāi)發(fā)大行其道的今天,人們通常將可以重用的軟件模塊稱為“軟件組件”。在全面向?qū)ο蟮?NET 軟件平臺(tái)之上,軟件組件的表現(xiàn)形式為程序集(Assembly),可以通過(guò)在Visual Studio 中創(chuàng)建并編譯一個(gè)類庫(kù)項(xiàng)目得到一個(gè)程序集。在Visual Studio 的項(xiàng)目模板中,可以很方便地創(chuàng)建類庫(kù)(Class Library)項(xiàng)目,Visual Studio 會(huì)自動(dòng)在項(xiàng)目中添加一個(gè)名為Class1.cs 的類文件,程序員可在此類文件中書(shū)寫代碼,或者添加新的類。一個(gè)類庫(kù)項(xiàng)目中可以容納的類數(shù)目沒(méi)有限制,但只有聲明為public 的類可以被外界使用。類庫(kù)項(xiàng)目編譯之后,會(huì)生成一個(gè)動(dòng)態(tài)鏈接庫(kù)(DLL:Dynamic Link Library)文件。這就是可以被重用的.NET 軟件組件——程序集。默認(rèn)情況下,類庫(kù)文件名就是項(xiàng)目名加上“.dll”后綴。每個(gè)類庫(kù)項(xiàng)目都擁有一個(gè)默認(rèn)的命名空間,可以通過(guò)類庫(kù)項(xiàng)目的屬性窗口來(lái)指定。需要仔細(xì)區(qū)分“類庫(kù)項(xiàng)目”、“程序集”和“命名空間”這三個(gè)概念的區(qū)別:

      (1)每個(gè)類庫(kù)項(xiàng)目編譯之后,將會(huì)生成一個(gè)程序集。

      (2)類庫(kù)項(xiàng)目中可以擁有多個(gè)類,這些類可屬于不同的命名空間。

      (3)不同的類庫(kù)項(xiàng)目可以定義相同的命名空間。

      根據(jù)上述三個(gè)特性,可以得到以下結(jié)論:“命名空間”是一個(gè)邏輯上的概念,它的物理載體是“程序集”,具體體現(xiàn)為“DLL”(或EXE)文件。在Visual Studio 中,可通過(guò)創(chuàng)建“類庫(kù)”類型的項(xiàng)目生成程序集。一個(gè)程序集可以有多個(gè)命名空間,而一個(gè)命名空間也可以分布于多個(gè)程序集。一旦生成了一個(gè)程序集,在其他項(xiàng)目中就可以通過(guò)添加對(duì)這一程序集的引用而使用此程序集中的類。其方法是在“項(xiàng)目”菜單中選擇“添加程序集”命令,激活“瀏覽”卡片,選擇一個(gè)現(xiàn)有的程序集文件(DLL 或EXE)。一個(gè)項(xiàng)目添加完對(duì)特定程序集的引用之后,就可以直接創(chuàng)建此程序集中的類了,當(dāng)然要注意指明其命名空間。

      八、委托

      委托是一種新的面向?qū)ο笳Z(yǔ)言特性,在歷史比較長(zhǎng)的面向?qū)ο笳Z(yǔ)言比如C++中并未出現(xiàn)過(guò)。微軟公司在設(shè)計(jì)運(yùn)行于.NET Framework平臺(tái)之上的面向?qū)ο笳Z(yǔ)言(如C#和VisualBasic.NET)時(shí)引入了這一新特性。委托(delegate)也可以看成是一種數(shù)據(jù)類型,可以用于定義變量。但它是一種特殊的數(shù)據(jù)類型,它所定義的變量能接收的數(shù)值只能是一個(gè)函數(shù),更確切地說(shuō),委托類型的變量可以接收一個(gè)函數(shù)的地址,很類似于C++語(yǔ)言的函數(shù)指針。簡(jiǎn)單地說(shuō):委托變量可看成是一種類型安全的函數(shù)指針,它只能接收符合其要求的函數(shù)地址。委托可以看成是一個(gè)函數(shù)的“容器”,將某一具體的函數(shù)“裝入”后,就可以把它當(dāng)成函數(shù)一樣使用。定義委托類型時(shí)對(duì)函數(shù)的要求被稱為函數(shù)的“簽名(signature)”。函數(shù)的簽名規(guī)定了函數(shù)的參數(shù)數(shù)目和類型,以及函數(shù)的返回值,體現(xiàn)了函數(shù)的本質(zhì)特征。每一個(gè)委托都確定了一個(gè)函數(shù)的簽名。擁有不同簽名的函數(shù)不能賦值給同一類型的委托變量。因此,一個(gè)委托類型的變量,可以引用任何一個(gè)滿足其要求的函數(shù)。

      1.委托的組合與分解

      委托變量可以代表某一函數(shù),使用委托變量就相當(dāng)于調(diào)用一個(gè)函數(shù)。如果僅是這么簡(jiǎn)單,那么直接調(diào)用函數(shù)不就行了嗎?為什么還要引入“委托”這一特性?事實(shí)上,委托不僅可以代表一個(gè)函數(shù),還可以組合“一堆”的函數(shù),然后批量執(zhí)行它們,這樣的委托變量又稱為“多路委托變量”??梢杂眉臃ㄟ\(yùn)算符來(lái)組合單個(gè)委托變量為多路委托變量。類似地,也可以使用減法運(yùn)算符來(lái)從一個(gè)多路委托變量中移除某個(gè)委托變量。

      2.事件與多路委托

      事件的主要特點(diǎn)是一對(duì)多關(guān)聯(lián),即一個(gè)事件源,多個(gè)響應(yīng)者。在具體技術(shù)上,.NET Framework 的事件處理機(jī)制是基于多路委托實(shí)現(xiàn)的。事件與多路委托其實(shí)大同小異,只不過(guò)多路委托允許在事件源對(duì)象之外激發(fā)事件罷了。所有的.NET Framework 可視化窗體控件的預(yù)定義事件,都是某一對(duì)應(yīng)的“事件名+Handler”委托類型的變量。與此事件相關(guān)的信息都封裝在“事件名+Args”類型的事件參數(shù)中,此事件參數(shù)有一個(gè)基類EventArgs,它是所有事件參數(shù)的基類。明了上述內(nèi)部機(jī)理,對(duì)于我們?cè)诔绦蛑卸x自己的事件非常有好處,尤其是開(kāi)發(fā)一個(gè)自定義的可視化控件時(shí),如果需要增加新的事件類型,我們應(yīng)盡量遵循.NET Framework 的定義事件的框架,給事件取一個(gè)名字,定義一個(gè)“事件名+Handler”的事件委托類型,再?gòu)腅ventArgs 派生出自定義事件的參數(shù),取名為“事件名+Args”。

      面向?qū)ο蟮能浖到y(tǒng)有許多都是事件驅(qū)動(dòng)的,ASP.NET 就采用了“事件驅(qū)動(dòng)”的編程方式。所謂“事件驅(qū)動(dòng)”的開(kāi)發(fā)方式,就是指整個(gè)系統(tǒng)包含許多的對(duì)象,這些對(duì)象可以引發(fā)多種事件,軟件工程師的主要開(kāi)發(fā)工作就是針對(duì)特定的事件書(shū)寫代碼響應(yīng)它們。.NET 事件處理機(jī)制建立在委托的基礎(chǔ)之上,而這兩者都是ASP.NET 技術(shù)的基礎(chǔ)之一。因此,必須牢固地掌握好委托和事件這兩種編程技術(shù),才能為掌握ASP.NET 技術(shù)掃清障礙。

      第四篇:C#總結(jié)

      引用類型是類型安全的指針,它們的內(nèi)存是分配在堆(保存指針地址)上的。String、數(shù)組、類、接口和委托都是引用類型。

      強(qiáng)制類型轉(zhuǎn)換與as類型轉(zhuǎn)換的區(qū)別:當(dāng)類型轉(zhuǎn)換非法時(shí),強(qiáng)制類型轉(zhuǎn)換將拋出一System.InvalidCastException異常,而as不會(huì)拋出異常,它返回一個(gè)null值。用using創(chuàng)建別名:using console = System.Console;訪問(wèn)限定符:

      public 該成員可以被其他任何類訪問(wèn) protected 該成員只能被其派生類訪問(wèn)

      private 該成員只能被本類的其他成員訪問(wèn) internal 該成員只能在當(dāng)前編譯單元的其他成員訪問(wèn) 帶參數(shù)列表和返回值的Main方法: class Test {

      public static int Main(string[] args)

      {

      foreach(string arg in args)

      {

      ...}

      } } 構(gòu)造函數(shù)(constructor)包括實(shí)例構(gòu)造函數(shù)和靜態(tài)構(gòu)造函數(shù)。構(gòu)造函數(shù)與類名相同,且不能有返回值。例:

      class TestClass {

      TestClass()//實(shí)例構(gòu)造函數(shù):可以訪問(wèn)靜態(tài)成員和實(shí)例成員,用于初始化實(shí)例成員

      {

      ...}

      static TestClass()//靜態(tài)構(gòu)造函數(shù):只能訪問(wèn)靜態(tài)成員,用于初始化靜態(tài)成員

      {

      ...} } 類的靜態(tài)成員屬于類所有,不必生成實(shí)例就可以訪問(wèn),它是在載入包含類的應(yīng)用程序時(shí)創(chuàng)建的,但靜態(tài)方法不能訪問(wèn)類的實(shí)例變量和方法。通常,靜態(tài)變量是在定義時(shí)就賦初始值的。類的實(shí)例成員屬于類的實(shí)例所有,不創(chuàng)建實(shí)例對(duì)象就無(wú)法對(duì)其進(jìn)行訪問(wèn),實(shí)例成員可以訪問(wèn)類的

      靜態(tài)成員和其它實(shí)例成員。調(diào)用基類的析構(gòu)函數(shù): class A {

      public A()

      {

      ...} } class B {

      public B(): base()//調(diào)用基類的析構(gòu)函數(shù)

      {

      ...} } 常量:其值是在編譯時(shí)設(shè)定的,必須是數(shù)值文字。默認(rèn)狀態(tài)下常量是靜態(tài)的。例: class A {

      public const double pi = 3.1415;} 常量是編譯時(shí)就確定的值,只讀字段是在運(yùn)行才能確定的值。比如運(yùn)行時(shí)才能確定的屏幕分辨率。

      只讀字段只能在類的析構(gòu)函數(shù)中賦值。靜態(tài)只讀字段: class A {

      public static readonly int ScreenWidth;//靜態(tài)只讀字段

      static A()

      //靜態(tài)析構(gòu)函數(shù)

      {

      ScreenWidth = 1024;//在靜態(tài)析構(gòu)函數(shù)中初始化

      } } 在類的繼承中,類的析構(gòu)函數(shù)是不會(huì)被繼承的。一個(gè)派生類只能從一個(gè)基類繼承,不能同時(shí)從多個(gè)基類繼承,但可以通過(guò)繼承多個(gè)接口來(lái)達(dá)到相同目的。實(shí)現(xiàn)多繼承的唯一方法就是使用接口。例:

      class MyFancyGrid: Control, ISerializable, IDataBound {...} 密封類是不能繼承的類,抽象類不能被定義為密封類,且密封類的私有成員不能用protected修飾,只能用private。例: sealed class A {...} 關(guān)鍵字ref和out用于指定用引用方式傳遞方法的參數(shù)。

      它們的區(qū)別是:ref參數(shù)必須初始化,而out參數(shù)不需要初始化。所以在方法處理代碼依賴參數(shù)的初始化值時(shí)使用ref,不依賴初始化值時(shí)使用out。對(duì)out參數(shù)即使在傳遞前對(duì)其進(jìn)行了初始化,其值也不會(huì)傳遞到方法處理函數(shù)內(nèi)部。傳遞時(shí)系統(tǒng)會(huì)將其設(shè)為未初始化。所以在方法內(nèi)部必須對(duì)out參數(shù)進(jìn)行初始化。

      方法重載時(shí),必須參數(shù)數(shù)目和參數(shù)類型其中之一不同,返回值不同不能作為重載。C#不支持方法的默認(rèn)值,只能通過(guò)方法重載來(lái)實(shí)現(xiàn)。例: class A {

      int Method(int a)

      {

      ...}

      void Method(int a, int b)//參數(shù)數(shù)目不同

      {

      //返回值不同不能作為重載

      ...} } params參數(shù)用于一個(gè)不定數(shù)目參數(shù)的方法,一般后面跟一個(gè)數(shù)組。例: class A {

      public void Method(params int[] i)

      {

      ...} } 方法的覆蓋:指派生類覆蓋基類的同名方法,有二種方法

      1)第一種是在派生類要覆蓋的方法前面加new修飾,而基類不需要作任何改動(dòng)。這種方法的缺點(diǎn)是不能實(shí)現(xiàn)多態(tài)。例: class A {

      public void Method()//無(wú)需任何修飾

      {

      ...} } class B: A

      //從基類繼承

      {

      new public void Method()//覆蓋基類的同名方法

      {

      ...} } class TestClass {

      A Instance = new B();

      Instance.Method();//這時(shí)將調(diào)用類A的Method方法,而不是類B的Method方法 } 2)第二種是在派生類要覆蓋的方法前面加override修飾,而基類的同名方法前面加virtual修飾。這樣就能實(shí)現(xiàn)多態(tài),例: class A {

      virtual public void Method()

      //基類定義虛方法

      {

      //虛擬方法不能定義為private,因?yàn)閜rivate成員對(duì)派生類是無(wú)法訪問(wèn)的...} }

      class B: A

      //從基類繼承 {

      override public void Method()

      //派生類覆蓋基類的同名虛方法

      {

      ...} } class TestClass {

      protected void Test()

      {

      A Instance = new B();

      //定義一個(gè)實(shí)例,類型為基類,從派生類創(chuàng)建

      //派生類總是能夠向上轉(zhuǎn)換為其基類

      Instance.Method();

      //將調(diào)用派生類B的Method方法,而不是基類的,這就是多態(tài)

      } } 說(shuō)明:new修飾的方法覆蓋不能實(shí)現(xiàn)多態(tài)的原因,是因?yàn)槭褂胣ew時(shí)編譯器只會(huì)實(shí)現(xiàn)早期綁定(early binding)。即調(diào)用的方法在編譯時(shí)就決定了:編譯器看到Instance.Method()而Instance的類是A,就會(huì)調(diào)用類A的Method()方法。

      override修飾的方法覆蓋可以實(shí)現(xiàn)多態(tài)的原因,是因?yàn)閷?shí)現(xiàn)了后期綁定(late binding)。使用override時(shí)強(qiáng)制編譯器在運(yùn)行時(shí)根據(jù)類的真正類型正確調(diào)用相應(yīng)的方法,而不是在編譯時(shí)。

      而基類的同名方法必須加virtual修飾。

      類的靜態(tài)方法可能通過(guò) 類名.靜態(tài)方法名 這種格式來(lái)調(diào)用,不能使用 實(shí)例名.靜態(tài)方法名 這種方法調(diào)用。

      因?yàn)轭惖撵o態(tài)方法為類所有(是屬于類本身的),而非實(shí)例所有(不是屬于類的實(shí)例的)。類的靜態(tài)方法可以訪問(wèn)類的任何靜態(tài)成員,但不能訪問(wèn)類的實(shí)例成員。C#中類的變量稱為字段。類的public變量稱為類的公共字段。

      類的屬性由一個(gè)protected(也可以是private)字段和getter和setter方法構(gòu)成: class Address {

      protected string zipCode;//protected字段,注意大小寫

      public string ZipCode

      {

      get

      //getter方法

      {

      return zipCode;

      }

      set

      //setter方法

      {

      zipCode = value;//被傳遞的值自動(dòng)被在這個(gè)value變量中

      }

      };} 只讀屬性是指省略setter方法的屬性,只讀屬性只能讀取,不能設(shè)置。

      屬性也可以用限定符virtual,override和abstract修飾,功能同其他類的方法。

      屬性有一個(gè)用處稱為懶惰的初始化(lazy initialization)。即在需要類成員時(shí)才對(duì)它們進(jìn)行初始化。如果類中包含了很少被引用的成員,而這些成員的初始化又會(huì)花費(fèi)大量的時(shí)候和系統(tǒng)資源的話,懶惰的初始化就很有用了。C#中數(shù)組對(duì)象共同的基類是System.Array。將數(shù)組聲明為類的一個(gè)成員時(shí),聲明數(shù)組與實(shí)例化數(shù)組必須分開(kāi),這是因?yàn)橹荒茉谶\(yùn)行時(shí)創(chuàng)建了類的實(shí)例對(duì)象之后,才能實(shí)例化數(shù)組元素值。聲明:

      int[] intArray;//一維數(shù)組 int[,] int3Array;//三維數(shù)組 初始化:

      intArray = new int[3] {1,2,3};int[,] int2Array = new int[2,3] {{1,2,3},{4,5,6}};//聲明時(shí)可以初始化 遍歷:

      1)一維數(shù)組

      for(int i = 0;i < intArray.Length;i++);//Array.Length返回?cái)?shù)組所有元素的個(gè)數(shù) foreach(int i in intArray);for(int i = 0;i < intArray.GetLength(0);i++);//Array.GetLength(0)返回?cái)?shù)組第一維的個(gè)數(shù) 2)多維數(shù)組

      for(int i = 0;i < int3Array.GetLength(0);i++)//遍歷三維數(shù)組

      for(int j = 0;j < int3Array.GetLength(1);j++)

      for(int k = 0;k < int3Array.GetLength(2);k++)

      {

      ...} 數(shù)組的維數(shù)就是該數(shù)組的秩(Rank)。Array.Rank可以返回?cái)?shù)據(jù)的秩。鋸齒數(shù)組(jagged Array)是元素為數(shù)組的數(shù)組,例:

      int[][] jaggedArray = new int[2][];//包含二個(gè)元素,每個(gè)元素是個(gè)數(shù)組 jaggedArray[0] = new int[2];//每個(gè)元素必須初始化 jaggedArray[1] = new int[3];for(int i = 0;i < jaggedArray.Length;i++)//遍歷鋸齒數(shù)組

      for(int j = 0;j < jaggedArray[i].Length;j++)

      {

      ...} 類的屬性稱為智能字段,類的索引器稱為智能數(shù)組。由于類本身作數(shù)組使用,所以用this作索引器的名稱,索引器有索引參數(shù)值。例: using System;using System.Collections;class MyListBox {

      protected ArrayList data = new ArrayList();

      public object this[int idx] //this作索引器名稱,idx是索引參數(shù)

      {

      get

      {

      if(idx >-1 && idx < data.Count)

      {

      return data[idx];

      }

      else

      {

      return null;

      }

      }

      set

      {

      if(idx >-1 && idx < data.Count)

      {

      data[idx] = value;

      }

      else if(idx = data.Count)

      {

      data.Add(value);

      }

      else

      {

      //拋出一個(gè)異常

      }

      }

      } } 接口是二段不同代碼之間約定,通過(guò)約定實(shí)現(xiàn)彼此之間的相互訪問(wèn)。C#并不支持多繼承,但通過(guò)接口可實(shí)現(xiàn)相同功能。當(dāng)在接口中指定了實(shí)現(xiàn)這個(gè)接口的類時(shí),我們就稱這個(gè)類“實(shí)現(xiàn)了該接口”或“從接口繼承”。一個(gè)接口基本上就是一個(gè)抽象類,這個(gè)抽象類中除了聲明C#類的其他成員類型——例如屬性、事件和索引器之外,只聲明了純虛擬方法。接口中可以包含方法、屬性、索引器和事件——其中任何一種都不是在接口自身中來(lái)實(shí)現(xiàn)的。例:

      interface IExampleInterface {

      //property declaration

      int testProperty { get;}

      //event declaration

      event testEvevnt Changed;

      //mothed declaration

      function void testMothed();

      //indexer declaration

      string this[int index] { get;set;} } 說(shuō)明:定義接口時(shí),在方法、屬性、事件和索引器所有這些接口成員都不能用public之類的訪問(wèn)限定符,因?yàn)樗薪涌诔蓡T都是public類型的。因?yàn)榻涌诙x了一個(gè)約定,任何實(shí)現(xiàn)一個(gè)接口的類都必須定義那個(gè)接口中每一個(gè)成員,否則將編譯失敗。例: using System;public class FancyControl {

      protected string data;

      public string Data

      {

      get {return this.data;}

      set {data = value;}

      } } interface IValidate {

      bool Validate();//接口方法

      } public class MyControl: FancyControl, IValidate {

      public MyControl()

      {

      data = “my control data”;

      }

      public bool Validate()//實(shí)現(xiàn)接口

      {

      if(data == “my control data”)

      return true;

      else

      return false;

      } } class InterfaceApp {

      MyControl myControl = new MyControl();

      IValidate val =(IValidate)myControl;//可以將一個(gè)實(shí)現(xiàn)某接口的類,轉(zhuǎn)換成該接口

      bool success = val.Validate();//然后可調(diào)用該接口的方法 } 也可以用:bool success = myControl.Validate();這種方法來(lái)調(diào)用Validate方法,因?yàn)閂alidate在類MyControl中是被定義成public的,如果去除public,Validate方法被隱藏,就不能用這種方法調(diào)用了,這樣隱藏接口方法稱為名字隱藏(name hiding)??梢杂茫侯悓?shí)例 is 接口名 來(lái)判斷某個(gè)類是否實(shí)現(xiàn)了某接口,例: myControl is IValidate //MyControl類的實(shí)例myControl是否實(shí)現(xiàn)了IValidate接口

      當(dāng)然,也可用as來(lái)作轉(zhuǎn)換,根據(jù)轉(zhuǎn)換結(jié)果是否為null來(lái)判斷某個(gè)類是否實(shí)現(xiàn)了某接口,例: IValidate val = myControl as IValidate;if(null == val){...//沒(méi)有實(shí)現(xiàn)IValidate接口 } else {...//實(shí)現(xiàn)了IValidate接口

      }

      如果一個(gè)類從多個(gè)接口繼承,而這些接口中如果定義的同名的方法,則實(shí)現(xiàn)接口的方法時(shí),必須加接口名來(lái)區(qū)別,寫成 接口名.方法名。假設(shè)Test類從IDataStore和ISerializable二個(gè)接口繼承,而這二個(gè)接口都有SaveData()方法,實(shí)現(xiàn)SaveData()方法時(shí)必須寫成: class Test: ISerializable, IDataStore {

      void ISerializable.SaveData()

      {

      ...}

      void IDataStore.SaveData()

      {

      ...} } 如果一個(gè)類從多個(gè)接口繼承,為了方便可以定義一個(gè)新的接口,這個(gè)接口繼續(xù)多個(gè)接口,然后類直接從這個(gè)接口繼承就可以了,這個(gè)叫合并接口。例: interface ISaveData: ISerializable, IDataStore { //不需要定義任何方法或成員,只是用作合并 } class Test: ISaveData //只要繼承ISaveData就可以了 {...} C# 操作符優(yōu)先級(jí)(從高到低)

      初級(jí)操作符()x.y f(x)a[x] x++ x--new typeof sizeof checked unchecked 一元操作符 +位移操作符 << >> 關(guān)系操作符 < > <= >= is 等于操作符 == 邏輯與

      & 邏輯異或 ^ 邏輯或

      | 條件與

      && 條件或

      || 條件操作符 ?: 賦值操作符 = *= /= %= +=-= <<= >>= &= ^= |= 所有的二元操作符除賦值符外都是左聯(lián)合的,即從左到右計(jì)算。

      typeof()運(yùn)算符可以從一個(gè)類名得到一個(gè)System.Type對(duì)象,而從System.Object對(duì)象繼承來(lái)的GetType()方法則可從一個(gè)類實(shí)例來(lái)得到一個(gè)System.Type對(duì)象。例: Type t1 = typeof(Apple);//Apple是一個(gè)類名

      Apple apple = new Apple();//apple是Apple類的一個(gè)實(shí)例 Type t2 = apple.GetType();//t1與t2是相同的 通過(guò)反射得到一個(gè)類的所有成員和方法: Type t = typeof(Apple);string className = t.ToString();//得到類名

      MethodInfo[] methods = t.GetMethods();//得到所有方法 foreach(MethodInfo method in methods){ //用method.ToString()得到方法名 } MemberInfo[] members = t.GetMembers();//得到所有成員 foreach(MemberInfo member in members){ //用member.ToString()得到成員名 } sizeof()操作符用來(lái)計(jì)算值類型變量在內(nèi)存中占用的字節(jié)數(shù)(Bytes),并且它只能在unsafe(非安全)

      代碼中使用。例:

      static unsafe public void ShowSizes(){

      int i, j;

      j = sizeof(short);

      j = sizeof(i);} 盡可能使用復(fù)合賦值操作符,它比不用復(fù)合賦值操作符的效率高。for語(yǔ)句的語(yǔ)法為:

      for(initialization;Boolean-expression;step)

      embedded-statement 在initialization和step部份還可以使用逗號(hào)操作符,例: for(int i = '0', j = 1;i <= 'xFF';i++, j++)for(int i = 1, j = 1;i < 1000;i += j, j = i!~ ++--true false 二元:+32)/ 9)* 5;

      } } 代表的(delegate)目的與C++中的函數(shù)指針相同,代表不是在編譯時(shí)被定義的,而是在運(yùn)行時(shí)被定義的。

      代表主要有二個(gè)用途:回調(diào)(Callback)和事件處理(event)回調(diào)通常用于異步處理和自定義處理。例: class DBManager {

      static DBConnection[] activeConnections;

      //聲明回調(diào)函數(shù)

      public void delegate EnumConnectionCallback(DBConnection connection);

      public static void EnumConnections(EnumConnectionCallback callback)

      {

      foreach(DBConnection connection in activeConnections)

      {

      callback(connection);//執(zhí)行回調(diào)函數(shù)

      }

      } } //調(diào)用

      class DelegateApp {

      public static void ActiveConncetionCallback(DBConnection connection)//處理函數(shù)

      {

      ...}

      public void main()

      {

      //創(chuàng)建指向具體處理函數(shù)的代表實(shí)例(新建一個(gè)代表,讓它指向具體的處理函數(shù))

      DBManager.EmnuConnectionCallback myCallback = new DBManager.EmnuConnectionCallback(ActiveConncetionCallback);

      DBManager.EnumConnections(myCallback);

      } } //使用靜態(tài)代表,上面的調(diào)用改為 class DelegateApp {

      //創(chuàng)建一個(gè)指向處理函數(shù)的靜態(tài)代表

      public static DBManager.EmnuConnectionCallback myCallback

      = new DBManager.EmnuConnectionCallback(ActiveConncetionCallback);

      public static void ActiveConncetionCallback(DBConnection connection)

      {...} public void main()

      {

      DBManager.EnumConnections(myCallback);

      } } //在需要時(shí)才創(chuàng)建代表,上面的調(diào)用改為

      class DelegateApp {

      //將創(chuàng)建代表放在屬性的getter方法中

      public static DBManager.EmnuConnectionCallback myCallback

      {

      get

      {

      retun new DBManager.EmnuConnectionCallback(ActiveConncetionCallback);

      }

      }

      public static void ActiveConncetionCallback(DBConnection connection)

      {...} public void main()

      {

      DelegateApp app = new DelegateApp();//創(chuàng)建應(yīng)用程序

      DBManager.EnumConnections(myCallback);

      } } 可以將多個(gè)代表整合成單個(gè)代表,例: class CompositeDelegateApp {

      public static void LogEvent(Part part)

      {

      ...}

      public static void EmailPurchasingMgr(Part part)

      {

      ...}

      public static void Main()

      {

      //定義二個(gè)代表

      InventoryManager.OutOfStockExceptionMethod LogEventCallback

      = new InventoryManager.OutOfStockExceptionMethod(LogEvent);

      InventoryManager.OutOfStockExceptionMethod EmailPurchasingMgrCallback

      = new InventoryManager.OutOfStockExceptionMethod(EmailPurchasingMgr);

      //整合為一個(gè)代表,注意后加的代表先執(zhí)行(這里是先執(zhí)行LogEventCallback)

      InventoryManager.OutOfStockExceptionMethod onHandExceptionEventsCallback

      = EmailPurchasingMgrCallback + LogEventCallback;

      //調(diào)用代表

      InventoryManager mgr = new InventoryManager();

      mgr.ProcessInventory(onHandExceptionEventsCallback);

      //InventoryManager類的ProcessInventory方法的原型為:

      //public void ProcessInventory(OutOfStockExceptionMethod exception);

      } } 可以根據(jù)需要將多個(gè)代表自由地組合成單個(gè)代表,例: class CompositeDelegateApp {

      //代表指向的處理函數(shù)(三個(gè)代表三個(gè)函數(shù))

      public static void LogEvent(Part part)

      {

      ...} public static void EmailPurchasingMgr(Part part){...}

      public static void EmailStoreMgr(Part part)

      {

      ...}

      public static void Main()

      {

      //通過(guò)數(shù)組定義三個(gè)代表

      InventoryManager.OutOfStockExceptionMethod[] exceptionMethods

      = new InventoryManager.OutOfStockExceptionMethod[3];

      exceptionMethods[0] = new InventoryManager.OutOfStockExceptionMethod(LogEvent);

      exceptionMethods[1] = new InventoryManager.OutOfStockExceptionMethod(EmailPurchasingMgr);

      exceptionMethods[2] = new InventoryManager.OutOfStockExceptionMethod(EmailStoreMgr);

      int location = 1;

      //再定義一個(gè)代表(用于組合成單代表)

      InventoryManager.OutOfStockExceptionMethod compositeDelegate;

      //根據(jù)需要組合

      if(location = 2)

      {

      compositeDelegate = exceptionMethods[0] + exceptionMethods[1];

      }

      else

      {

      compositeDelegate = exceptionMethods[0] + exceptionMethods[2];

      }

      //調(diào)用代表

      InventoryManager mgr = new InventoryManager();

      mgr.ProcessInventory(compositeDelegate);

      } } C#的事件遵循“發(fā)布——預(yù)訂”的設(shè)計(jì)模式。在這種模式中,一個(gè)類公布能夠出現(xiàn)的所有事件,然后任何的類都可以預(yù)訂這些事件。一旦事件產(chǎn)生,運(yùn)行環(huán)境就負(fù)責(zé)通知每個(gè)訂戶事件已經(jīng)發(fā)生了。

      當(dāng)代表作為事件的處理結(jié)果時(shí)(或者說(shuō)定義具有代表的事件),定義的代表必須指向二個(gè)參數(shù)的方法:一個(gè)參數(shù)是引發(fā)事件的對(duì)象(發(fā)布者),另一個(gè)是事件信息對(duì)象(這個(gè)對(duì)象必須從EventArgs類中派生)。例: using System;

      class InventoryChangeEventArgs: EventArgs //事件信息對(duì)象,從EventArgs類派生 {...//假設(shè)定義二個(gè)public屬性string Sku和int Change } class InventoryManager

      //事件的發(fā)布者 {

      //聲明代表

      public delegate void InventoryChangeEventHander(object source, InventoryChangeEventArgs e);

      //發(fā)布事件,event關(guān)鍵字可將一個(gè)代表指向多個(gè)處理函數(shù)

      public event InventoryChangeEventHandler onInventoryChangeHander;

      public void UpdateInventory(string sku, int change)

      {

      if(change == 0)

      return;

      InventoryChangeEventArgs e = new InventoryChangeEventArgs(sku, change);

      //觸發(fā)事件

      if(onInventoryChangeHandler!= null)//如果有預(yù)訂者就觸發(fā)

      onInventoryChangeHandler(this, e);//執(zhí)行代表指向的處理函數(shù)

      } } class InventoryWatcher

      //事件的預(yù)訂者 {

      public InventoryWatcher(InventoryManager mgr)//mgr參數(shù)用于聯(lián)結(jié)發(fā)布者

      {

      this.inventoryManager = mgr;

      //預(yù)訂事件,用 += 調(diào)用多個(gè)處理函數(shù)

      mgr.onInventroyChangeHandler += new InventoryManager.InventoryChangeEventHandler(onInventoryChange);

      //事件處理函數(shù)

      void onInventroyChange(object source, InventroyChangeEventArgs e)

      {

      ...}

      InventoryManager inventoryManager;

      } } class EventsApp

      //主程序 {

      public static void Main()

      {

      InventoryManager inventoryManager = new InventoryManager();

      InventoryWatcher inventoryWatcher = new InventoryWatcher(inventoryManager);

      inventoryManager.UpdateInventory(“111 006 116”,-2);

      inventoryManager.UpdateInventory(“111 006 116”, 5);

      } } Microsoft Windows NT和IBM OS/2等操作系統(tǒng)都支持占先型多任務(wù)。在占先型多任務(wù)執(zhí)行中,處理器負(fù)責(zé)

      給每個(gè)線程分配一定量的運(yùn)行時(shí)間——一個(gè)時(shí)間片(timeslice)。處理器接著在不同的線程之間進(jìn)行切換,執(zhí)行相應(yīng)的處理。在單處理器的計(jì)算機(jī)上,并不能真正實(shí)現(xiàn)多個(gè)線程的同時(shí)運(yùn)行,除非運(yùn)行在多個(gè)處理器 的計(jì)算機(jī)上。操作系統(tǒng)調(diào)度的多線程只是根據(jù)分配給每個(gè)線程時(shí)間片進(jìn)行切換執(zhí)行,感覺(jué)上就像同時(shí)執(zhí)行。

      上下文切換(context switching)是線程運(yùn)行的一部分,處理器使用一個(gè)硬件時(shí)間來(lái)判斷一個(gè)指定線程的時(shí)間片何時(shí)結(jié)束。當(dāng)這個(gè)硬件計(jì)時(shí)器給出中斷信號(hào)時(shí),處理器把當(dāng)前運(yùn)行的線程所用的所有寄存器(registers)數(shù)據(jù)存儲(chǔ)到堆棧中。然后,處理器把堆棧里那些相同的寄存器信息存放到一種被稱為“上下文結(jié)構(gòu)”的數(shù)據(jù)結(jié)構(gòu)中。當(dāng)處理器要切換回原來(lái)執(zhí)行的線程時(shí),它反向執(zhí)行這個(gè)過(guò)程,利用與該線程相關(guān)的上下文結(jié)構(gòu),在寄存器里重新恢復(fù)與這一線程相關(guān)的信息。這樣的一個(gè)完整過(guò)程稱為“上下文切換”。多線程允許應(yīng)用程序把任務(wù)分割為多個(gè)線程,它們彼此之間可以獨(dú)立地工作,最大限度地利用了處理器時(shí)間。using System;using System.Threading;class SimpleThreadApp {

      public static void WorkerThreadMethod()//線程的執(zhí)行體

      {

      ...//執(zhí)行一些操作

      }

      public static void Main()

      {

      //創(chuàng)建一個(gè)線程代表指向線程的執(zhí)行體,ThreadStart是創(chuàng)建新線程必須用到的代表

      ThreadStart worker = new ThreadStart(WorkerThreadMethod);

      Thread t = new Thread(worker);//用線程代表創(chuàng)建線程

      t.Start();

      //執(zhí)行線程

      } } 可以通過(guò)兩種方式來(lái)得到一個(gè)Thread對(duì)象:一種是通過(guò)創(chuàng)建一個(gè)新線程來(lái)得到,如上例;另一種在正在執(zhí)行的線程調(diào)用靜態(tài)的Thread.CurrentThread方法。

      靜態(tài)方法Thread.Sleep(int ms)可以讓當(dāng)前線程(它自動(dòng)調(diào)用Thread.CurrentThread)暫停指定毫秒的時(shí)間。

      如果使用Thread.Sleep(0)那么當(dāng)前線程將一直處于等待中,直到另一個(gè)線程調(diào)用這個(gè)線程的實(shí)例方法Thread.Interrupt方法,等待才會(huì)結(jié)束。使用Thread.Suspend方法也能掛起線程,Thread.Suspend方法可以被當(dāng)前線程或其他線程調(diào)用,而Thread.Sleep(0)只能由當(dāng)前線程在執(zhí)行體中調(diào)用。當(dāng)線程用Thread.Suspend掛起時(shí),必須用Thread.Resume方法恢復(fù)。不論Thread.Suspend方法調(diào)用了多少次,只要調(diào)用Thread.Resume方法一次就可以線程恢復(fù)執(zhí)行。用Thread.Suspend方法并不會(huì)阻塞線程,調(diào)用立即返回。而Thread.Sleep(0)則會(huì)阻塞線程。所以確切地說(shuō)Thread.Sleep(0)暫停線程,而不是掛起線程。

      使用Thread.Abort方法可以終止正在執(zhí)行的線程。當(dāng)Thread.Abort方法被調(diào)用時(shí),線程不會(huì)立即終止執(zhí)行。運(yùn)行環(huán)境將會(huì)等待,直到線程到達(dá)文檔中所描述的“安全點(diǎn)”。如果要確保線程已經(jīng)完全停止,可以使用Thread.Join方法。這是一個(gè)同步調(diào)用,同步調(diào)用意味著直到線程完全停止,調(diào)用才會(huì)返回。

      Thread.Priority屬性用于設(shè)置的線程的優(yōu)先級(jí)。其值是Thread.ThreadPriority枚舉值,可以設(shè)為Highest, AboveNormal,Normal, BelowNormal, Lowest。缺省值是Thread.ThreadPriority.Normal。

      線程的同步是為了解決多個(gè)線程同時(shí)使用同一對(duì)象產(chǎn)生的一些問(wèn)題。通過(guò)同步,可以指定代碼的臨界區(qū)(critical section),一次只有一個(gè)線程可以進(jìn)入臨界區(qū)。使用System.Monitor類(鎖定與信號(hào)量)進(jìn)行線程同步: using System;using System.Threading;public void SaveData(string text)//線程執(zhí)行函數(shù)或線程執(zhí)行函數(shù)調(diào)用的對(duì)象的方法 {

      ...//執(zhí)行其他一些不需要同步的處理

      Monitor.Enter(this);//獲取對(duì)象的Monitor鎖

      ...//執(zhí)行需要同步的處理

      Monitor.Exit(this);//釋放對(duì)象的Monitor鎖

      ...//執(zhí)行其他一些不需要同步的處理

      } 說(shuō)明:當(dāng)執(zhí)行Monitor.Enter方法時(shí)。這個(gè)方法會(huì)試圖獲取對(duì)象上的Monitor鎖,如果另一個(gè)線程已經(jīng)擁有了這個(gè)鎖,這個(gè)方法將會(huì)阻塞(block),直到這個(gè)鎖被釋放。

      也可用C#的lock語(yǔ)句來(lái)獲得和釋放一個(gè)Monitor鎖。上面同步寫成:public void SaveData(string text)//線程執(zhí)行函數(shù)或線程執(zhí)行函數(shù)調(diào)用的對(duì)象的方法 {

      ...//執(zhí)行其他一些不需要同步的處理

      lock(this)//獲取對(duì)象的Monitor鎖,代碼塊執(zhí)行完成后釋放Monitor鎖

      {

      ...//執(zhí)行需要同步的處理

      }

      ...//執(zhí)行其他一些不需要同步的處理 } 也可以使用System.Threading名稱空間的Mutex類(互斥類)進(jìn)行線程同步。與Monitor鎖一樣,一次只有一個(gè)線程能獲得一個(gè)給定的互斥。但Mutex要慢得多,但它增加了靈活性。例:

      using System;using System.Threading;class Database {

      Mutex mutex = new Mutex(false);//創(chuàng)建一個(gè)互斥,但不立即獲得它

      //注意:創(chuàng)建互斥在需要同步的方法之外,實(shí)際上它只要?jiǎng)?chuàng)建一個(gè)實(shí)例

      public void SaveData(string text)//需要同步的方法

      {

      mutex.WaitOne();//等待獲得互斥

      ...//需要同步的處理

      mntex.Close();//釋放互斥

      } } Mutex類重載了三個(gè)構(gòu)造函數(shù):

      Mutex()

      //創(chuàng)建并使創(chuàng)建類立即獲得互斥

      Mutex(bool initiallyOwned)

      //創(chuàng)建時(shí)可指定是否要立即獲得互斥 Mutex(bool initiallyOwned, string muterName)//還可以指定互斥的名稱 Mutex.WaitOne方法也重載了三次: Mutex.WaitOne()

      //一直等待

      Mutex.WaitOne(TimeSpan time, bool exitContext)//等待TimeSpan指定的時(shí)間 Mutex.WaitOne(int milliseconds, bool exitContext)//等待指定的毫秒 線程的用法:

      1)并發(fā)操作:比如一個(gè)程序監(jiān)視多個(gè)COM口,當(dāng)每個(gè)COM接到信息時(shí)執(zhí)行一段處理時(shí)。2)復(fù)雜長(zhǎng)時(shí)間操作:一個(gè)長(zhǎng)時(shí)間的復(fù)雜操作可能會(huì)使界面停滯,停止用戶響應(yīng),如果還允許用戶停止它,或者顯示進(jìn)度條、顯示操作執(zhí)行進(jìn)程信息時(shí)。

      反射(Reflection)就是能夠在運(yùn)行時(shí)查找類型信息,這是因?yàn)?NET編譯的可執(zhí)行(PE)文件中包括MSIL和元數(shù)據(jù)(metadata)。

      反射的中心是類System.Type。System.Type是一個(gè)抽象類,代表公用類型系統(tǒng)(Common Type System, CTS)中的一種類型。

      using System;using System.Reflection;//反射命名空間,必須引用 public static void Main(string[] args){

      int i = 6;

      Type t = i.GetType();

      //根據(jù)實(shí)例得到類型

      t = Type.GetType(“System.Int32”);//根據(jù)類型的字符名稱得到類型

      } 通過(guò)Assembly類可以得到已經(jīng)編譯.NET Framework程序的中所有類型,例: using System;using System.Diagnostics;//為了使用Process類 using System.Reflection;//為了使用Assembly類 class GetTypesApp {

      protected static string GetAssemblyName(string[] args)

      {

      string assemblyName;

      if(0 == args.Length)//如果參數(shù)為空,取當(dāng)前進(jìn)程的名稱

      {

      Process p = Process.GetCurrentProcess();

      assemblyName = p.ProcessName + “.exe”;

      }

      else

      assemblyName = args[0];//取第一個(gè)參數(shù),即當(dāng)前運(yùn)行程序名

      return assemblyName;

      }

      public static void Main(string[] args)

      {

      string assemblyName = GetAssemblyName(args);

      Assembly a = Assembly.LoadFrom(assemblyName);//調(diào)用編譯程序集

      Type[] types = a.GetTypes();

      //得到多個(gè)類型

      foreach(Type t in types)

      //遍歷類型數(shù)組

      {

      ...//取得t.FullName,t.BaseType.FullName等類型信息

      }

      } } 一個(gè)應(yīng)用程序可以包括多個(gè)代碼模塊。若要將一個(gè)cs文件編譯一個(gè)模塊,只要執(zhí)行下面的命令:

      csc /target:module 要編譯的模塊.cs //csc是C Sharp Compiler(C#編譯器)然后在應(yīng)用程序中using編譯的模塊.cs中的NameSpace即可應(yīng)用了。要反射應(yīng)用程序中所有代碼模塊(Module),只要:

      Assembly a = Assembly.LoadFrom(assemblyName);//應(yīng)用程序的物理文件名 Module[] modules = a.GetModules();foreach(Module m in modules){...//顯示m.Name等

      } 后期綁定(latebinding),例:

      string[] fileNames = Directory.GetFiles(Environment.CurrentDirectory, “*.dll”);foreach(string fileName in fileNames){

      Assembly a = Assembly.LoadFrom(fileName);

      Type[] types = a.GetTypes();

      foreach(Type t in types)

      {

      if(t.IsSubclassOf(typeof(CommProtocol)))//判斷是否有CommProtocol的派生類

      {

      object o = Activator.CreateInstance(t);//生成實(shí)例

      MethodInfo mi = t.GetMethod(“DisplayName”);

      mi.Invoke(o, null);

      //調(diào)用方法

      }

      } } //帶參數(shù)的例子

      namespace Programming_CSharp {

      using System;

      using System.Reflection;

      public class Tester

      {

      public static void Main()

      {

      Type t = Type.GetType(“System.Math”);

      Object o = Activator.CreateInstance(t);

      // 定義參數(shù)類型

      Type[] paramTypes = new Type[1];

      paramTypes[0]= Type.GetType(“System.Double”);

      MethodInfo CosineInfo = t.GetMethod(“Cos”, paramTypes);

      //設(shè)置參數(shù)數(shù)據(jù)

      Object[] parameters = new Object[1];

      parameters[0] = 45;

      //執(zhí)行方法

      Object returnVal = CosineInfo.Invoke(o, parameters);

      Console.WriteLine(“The cosine of a 45 degree angle {0}”, returnVal);

      }

      } } 動(dòng)態(tài)生成代碼和動(dòng)態(tài)調(diào)用的完整例子: //動(dòng)態(tài)生成代碼的部分 using System;using System.Reflection;using System.Reflection.Emit;//動(dòng)態(tài)生成代碼必須引用 namespace ILGenServer {

      public class CodeGenerator

      {

      public CodeGenerator()

      {

      currentDomain = AppDomain.CurrentDomain;//得到當(dāng)前域

      assemblyName = new AssemblyName();//從域創(chuàng)建一個(gè)程序集

      assemblyName.Name = “TempAssembly”;

      //得到一個(gè)動(dòng)態(tài)編譯生成器,AssemblyBuilerAccess.Run表示只在內(nèi)存中運(yùn)行,不能保存

      assemblyBuilder = currentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilerAccess.Run);

      //從編譯生成器得到一個(gè)模塊生成器

      moduleBuilder = assemblyBuilder.DefineDynamicModule(“TempModule”);

      //模塊生成器得到類生成器

      typeBuilder = moduleBuilder.DefineType(“TempClass”, TypeAttributes.Public);

      //為類添加一個(gè)方法

      methodBuilder = typeBuilder.DefineMethod(“HelloWord”, MethodAttributes.Public, null, null);

      //為方法寫入代碼,生成代碼必須使用到IL生成器

      msil = methodBuilder.GetILGenerator();

      msil.EmitWriteLine(“Hello World”);msil.Emit(OpCodes.Ret);//最后還需要編譯(build)一下類 t = typeBuilder.CreateType();

      }

      AppDomain currentDomain;

      AssemblyName assemblyName;

      AssemblyBuilder assemblyBuilder;

      ModuleBuilder moduleBuilder;

      TypeBuilder typeBuilder;

      MethodBuilder methodBuilder;

      ILGenerator msil;

      object o;

      Type t;

      public Type T

      {

      get

      {

      return this.t;

      }

      }

      } } //動(dòng)態(tài)調(diào)用的部分

      using System;using System.Reflection;using ILGenServer;//引用動(dòng)態(tài)生成代碼的類 public class ILGenClientApp {

      public static void Main({

      CodeGenerator gen = new CodeGenerator();//創(chuàng)建動(dòng)態(tài)生成類

      Type t = gen.T;

      if(null!= t)

      {

      object o = Activator.CreateInstance(t);

      MethodInfo helloWorld = t.GetMethod(“HelloWorld”);//為調(diào)用方法創(chuàng)建一個(gè)MethodInfo

      if(null!= helloWorld)

      {

      helloWorld.Invoke(o, null);//調(diào)用方法

      }

      }

      } } 調(diào)用DLL using System;using System.Runtime.InteropServices;//為了使用DLLImport特性

      class PInvokeApp {

      [DllImport(“user32.dll”, CharSet=CharSet.Ansi)] //CharSet.Ansi指定Ansi版本的函數(shù)(MessageBoxA),CharSet.Unicode指定Unicode版本的函數(shù)(MessageBoxW)

      static extern int MessageBox(int hWnd, string msg, string caption, int type);//聲明DLL中的函數(shù)

      //[DllImport(“user32.dll”, EntryPoint=“MessageBoxA”)] //用這種方法使用不同的函數(shù)名

      //static extern int MsgBox(int hWnd, string msg, string caption, int type);

      //[DllImport(“user32.dll”, CharSet=CharSet.Unicode)] //調(diào)用Unicode版的DLL函數(shù)

      //static extern int MessageBox(int hWnd, [MarshalAs(UnmanagedType.LPWStr)]string msg,// [MarshalAs(UnmanagedType.LPWStr)]string caption, int type);//將LPWStr翻譯為string型,缺省情況系統(tǒng)只將LPStr翻譯成string

      public static void Main()

      {

      MessageBox(0, “Hello, World!”, “CaptionString”, 0);//調(diào)用DLL中的函數(shù)

      } } 例2,使用回調(diào): class CallbackApp {

      [DllImport(“user32.dll”)]

      static extern int GetWindowText(int hWnd, StringBuilder text, int count);

      delegate bool CallbackDef(int hWnd, int lParam);

      [DllImport(“user32.dll”)]

      static extern int EnumWindows(CallbackDef callback, int lParam);

      static bool PrintWindow(int hWnd, int lParam)

      {

      StringBuilder text = new StringBuilder(255);

      GetWindowText(hWnd, text, 255);

      Console.WriteLine(“Window Caption: {0}”, text);

      return true;

      }

      static void Main()

      {

      CallbackDef callback = new CallbackDef(PrintWindow);

      EnumWindows(callback, 0);

      } } 關(guān)鍵字unsafe指定標(biāo)記塊在非控環(huán)境中運(yùn)行。該關(guān)鍵字可以用于所有的方法,包括構(gòu)造函數(shù)和屬性,甚至還有方法中的代碼塊。關(guān)鍵字fixed負(fù)責(zé)受控對(duì)象的固定(pinning)。Pinning是一種動(dòng)作,向垃圾收集(Garbage Collector, GC)指定一些不能被移動(dòng)的對(duì)象。為了不在內(nèi)存中產(chǎn)生碎片,.NET運(yùn)行環(huán)境把對(duì)象四處移動(dòng),以便于最有效地利用內(nèi)存。使用fixed后指定對(duì)象將不會(huì)被移動(dòng),所以就可以用指針來(lái)訪問(wèn)它。

      C#中只能得到值類型、數(shù)組和字符串的指針。在數(shù)組的情況下,第一個(gè)元素必須是值類型,因?yàn)镃#實(shí)際上是返回一個(gè)指向數(shù)組第一個(gè)元素的指針,而不是返回?cái)?shù)組自身。& 取一個(gè)變量的內(nèi)存地址(即指向該變量的指針)* 取指針?biāo)缸兞康闹?> 取成員

      例:using System;class UnsafeApp {

      public static unsafe void GetValues(int* x, int* y)

      {

      *x = 6;

      *y = 42;

      }

      public static unsafe void Main()

      {

      int a = 1;

      int b = 2;

      GetValues(&a, &b);

      } } fixed語(yǔ)法為:fixed(type* ptr = expression)statements其中type也可以為非控類型,也可是void;expression是任何產(chǎn)生一個(gè)type指針的表達(dá)式;statements是應(yīng)用的代碼塊。例: fixed(int* f = &foo.x)//foo是Foo類的一個(gè)實(shí)例,x是Foo類的一個(gè)int屬性 {

      SetFooValue(f);//SetFooValue方法的定義為unsafe static void SetFooValue(int* x)} 傳統(tǒng)的COM組件可以通過(guò)互操作層(COM Interop)與.NET運(yùn)行環(huán)境交互?;ゲ僮鲗犹幚碓谕泄苓\(yùn)行環(huán)境和非托管區(qū)域中的COM組件操作之間傳遞所有的消息。

      要使COM組件能在.NET環(huán)境中使用,必須為COM組件生成元數(shù)據(jù)。.NET運(yùn)行環(huán)境用元數(shù)據(jù)層業(yè)判斷類型信息。在運(yùn)行時(shí)刻使用類型信息,以便生成RCW(Runtime Callable Wrapper,運(yùn)行時(shí)可調(diào)用包裝)。當(dāng).NET應(yīng)用程序與COM對(duì)象交互時(shí),RCW處理對(duì)COM對(duì)象的裝載和調(diào)用。RCW還完成許多其他的工作,如管理對(duì)象標(biāo)識(shí)、對(duì)象生存周期以及接口緩沖區(qū)。對(duì)象生存周期管理十分關(guān)鍵,因?yàn)?NET GC把對(duì)象到處移動(dòng),并且當(dāng)對(duì)象不再使用時(shí),自動(dòng)處理這些對(duì)象。RCW服務(wù)告訴.NET,應(yīng)用程序正與托管.NET組件交互,同時(shí)又使非托管COM組件“覺(jué)得”COM對(duì)象是被傳統(tǒng)的COM客戶端調(diào)用的。

      為了為COM組件生成元數(shù)據(jù)包裝,必須使用tlbimp.exe(TypeLib Importer)工具: tlbimp some_COM.tlb /out:som_COM.dll

      第五篇:c#讀書(shū)筆記

      1、.NET平臺(tái)包括.NET框架和.NET開(kāi)發(fā)工具等組成部分。.NET框架是整個(gè)開(kāi)發(fā)平臺(tái)的基礎(chǔ),包括公共語(yǔ)言運(yùn)行庫(kù)和.NET類庫(kù)。.NET開(kāi)發(fā)工具包括Visual Studio.NET集成開(kāi)發(fā)環(huán)境和.NET編程語(yǔ)言。.NET框架(.NET Framework)是.NET開(kāi)發(fā)平臺(tái)的基礎(chǔ)。.NET框架提供了一個(gè)跨語(yǔ)言的、統(tǒng)一的、面向?qū)ο蟮拈_(kāi)發(fā)和運(yùn)行環(huán)境。

      2、在Visual Studio.NET集成開(kāi)發(fā)環(huán)境下,可以開(kāi)發(fā)多種不同類型的應(yīng)用程序。最常見(jiàn)的有以下幾種。

      ??刂婆_(tái)應(yīng)用程序

      。Windows應(yīng)用程序

      。ASP.NET網(wǎng)站

      3、開(kāi)發(fā)和運(yùn)行控制臺(tái)應(yīng)用程序

      創(chuàng)建一個(gè)控制臺(tái)應(yīng)用程序,主要包含以下步驟:

      (1)執(zhí)行文件—》新建—》項(xiàng)目

      (2)打開(kāi)“新建項(xiàng)目”對(duì)話框,在“項(xiàng)目類型”列表中選擇Visual c#節(jié)點(diǎn)下的Windows,在“模板”窗格中選擇“控制臺(tái)應(yīng)用程序”項(xiàng)目模板,輸入項(xiàng)目的名稱、位置及

      解決方案名稱后,單擊“確定”按鈕。

      (3)在打開(kāi)的.cs文件中編寫代碼。

      (4)運(yùn)行程序。執(zhí)行“調(diào)試”—》啟動(dòng)調(diào)試菜單命令,編譯并運(yùn)行程序

      4、c#程序的基本結(jié)構(gòu)

      。using關(guān)鍵字的功能是用于導(dǎo)入其它命名空間中定義的類型,包括.NET類庫(kù)。例如,代碼中使用的console.readline方法實(shí)際上是一個(gè)簡(jiǎn)寫,其全稱是system.console.readline,但由于在代碼的開(kāi)始使用using指令引入了system命名空間,所以后面可以直接使用console.readline來(lái)進(jìn)行輸入。

      。namespace 即“命名空間”,也稱“名稱空間”。命名空間是Visual Studio.NET中的各種語(yǔ)言使用的一種代碼組織的形式,當(dāng)編譯一個(gè)解決方案時(shí),系統(tǒng)會(huì)用項(xiàng)目名稱做名字,生成一個(gè)namespace,并把類都放在這個(gè)namespace里面。

      下載C#學(xué)習(xí)心得(五篇材料)word格式文檔
      下載C#學(xué)習(xí)心得(五篇材料).doc
      將本文檔下載到自己電腦,方便修改和收藏,請(qǐng)勿使用迅雷等下載。
      點(diǎn)此處下載文檔

      文檔為doc格式


      聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn)自行上傳,本網(wǎng)站不擁有所有權(quán),未作人工編輯處理,也不承擔(dān)相關(guān)法律責(zé)任。如果您發(fā)現(xiàn)有涉嫌版權(quán)的內(nèi)容,歡迎發(fā)送郵件至:645879355@qq.com 進(jìn)行舉報(bào),并提供相關(guān)證據(jù),工作人員會(huì)在5個(gè)工作日內(nèi)聯(lián)系你,一經(jīng)查實(shí),本站將立刻刪除涉嫌侵權(quán)內(nèi)容。

      相關(guān)范文推薦

        C#作業(yè)參考答案

        語(yǔ)句while(x>10 && x......

        C#課程設(shè)計(jì)報(bào)告書(shū)

        :課程設(shè)計(jì)報(bào)告書(shū) 面向?qū)ο蠓椒▽W(xué) 課 程 設(shè) 計(jì) 報(bào) 告 設(shè)計(jì)題目:學(xué)生信息管理系統(tǒng)課程 班 級(jí):13軟件工程1班 學(xué) 號(hào):20130*** 姓 名:何** 指導(dǎo)教師:莊**老師 設(shè)計(jì)時(shí)間:2014年12月 1 附......

        C#程序設(shè)計(jì)實(shí)驗(yàn)報(bào)告

        實(shí)驗(yàn)報(bào)告書(shū)寫要求實(shí)驗(yàn)報(bào)告原則上要求學(xué)生手寫,要求書(shū)寫工整。若因課程特點(diǎn)需打印的,標(biāo)題采用四號(hào)黑體,正文采用小四號(hào)宋體,單倍行距。紙張一律采用A4的紙張。 實(shí)驗(yàn)報(bào)告書(shū)寫說(shuō)明......

        C# 注釋規(guī)范

        C# 注釋(Comment)規(guī)范 注釋規(guī)范包括:模塊(類)注釋規(guī)范、類的屬性、方法注釋規(guī)范、代碼間注釋 1. 模塊(類)注釋規(guī)范 模塊開(kāi)始必須以以下形式書(shū)寫模塊注釋: /// ///模塊編號(hào): ///作用......

        C#實(shí)習(xí)總結(jié)

        現(xiàn)在的社會(huì)日新月異,科技飛速發(fā)展,但是隨之而來(lái)的環(huán)境問(wèn)題也日益嚴(yán)重,當(dāng)然這也有很多其他諸如人口、能源等因素,不過(guò)這些讓人們?cè)絹?lái)越重視綠色產(chǎn)業(yè),而軟件就是首當(dāng)其沖的一個(gè)。我......

        c#基礎(chǔ)總結(jié)

        【1】面向?qū)ο蟪绦蛟O(shè)計(jì)語(yǔ)言的三大特點(diǎn)是什么?答:【23】Main函數(shù)特點(diǎn)?答:1)Main方法是C#程序的限定,默認(rèn)的為private【2】三種命名法則的特點(diǎn)?答:匈牙利命名法:在變限定符,返回類型為vo......

        C#心得體會(huì)(5篇模版)

        ? C#心得體會(huì)10計(jì)算機(jī)應(yīng)用1班全博鵬 剛學(xué)習(xí)C#的時(shí)候,感覺(jué)很難,做的時(shí)候出現(xiàn)很多錯(cuò)誤而且我是照著書(shū)打代碼還有錯(cuò)誤,那時(shí)的感覺(jué)是迷茫的。在學(xué)習(xí)的過(guò)程中,我還是堅(jiān)持下來(lái),雖然學(xué)......

        C#期末總結(jié)

        C#期末總結(jié) 接觸C#已經(jīng)有半學(xué)期時(shí)間,對(duì)C#感觸頗多。C#作為邏輯性極強(qiáng),功能強(qiáng)大的程序編程語(yǔ)言,僅僅學(xué)習(xí)半學(xué)期是遠(yuǎn)遠(yuǎn)不夠的,希望自己能在這條路上不斷前行,能夠活到老學(xué)到老。跟......