C#學習筆記(個人)_第1頁
C#學習筆記(個人)_第2頁
C#學習筆記(個人)_第3頁
C#學習筆記(個人)_第4頁
C#學習筆記(個人)_第5頁
已閱讀5頁,還剩142頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、、C#基礎知識1 C#中 foreach 用法foreach循環(huán)用于列舉出集合中所有的元素,foreach語句中的表達式由關鍵字 in隔開的兩個項組成。in右邊的項是集合名,in左邊的項是變量名,用來存放 該集合中的每個元素。該循環(huán)的運行過程如下:每一次循環(huán)時,從集合中取出一個新的元素值。放到只 讀變量中去,如果括號中的整個表達式返回值為true, foreach塊中的語句就能 夠執(zhí)行。一旦集合中的元素都已經(jīng)被訪問到,整個表達式的值為false,控制流 程就轉入到foreach塊后面 的執(zhí)行語句。foreach語句經(jīng)常與數(shù)組一起使用,下面實例將通過foreach語句讀取數(shù)組的值 并進行顯示。數(shù)

2、組的屬性:Array. Length數(shù)組的容量利用這個屬性,我們可以取得數(shù)組對象允許存儲的容量值,也就是數(shù)組的長度、 元素個數(shù),這個比擬好理解,數(shù)組還有其他的屬性,比方數(shù)組的維數(shù)等,屬性的 用法比擬簡單,學會一種,其他的格式基本一致,這里我們就不舉例了。當數(shù)組的維數(shù)、容量較多時,C#提供了 foreach語句,專門用來讀取集合/數(shù)組 中的所有元素,我們把這種功能叫做遍歷。語法書寫如下:遍歷數(shù)組:foreach (type objName in collection/Array)這段語句會逐一檢查數(shù)組中的所存儲的變量值,并且一一將其取出,其中的type 是你所要讀取的數(shù)組對象將要存儲在objNa

3、me變量的數(shù)據(jù)類型,而objName是定 義了一個type類型的變量名,代表每一次從集合和數(shù)組(collection/Array) 中取得的元素,coHection/Array那么是所要存取的數(shù)組對象。用這種方法只需 寫一個foreach就可以遍歷出除交錯數(shù)組以外的所有維數(shù)的數(shù)組。例子:用foreach循環(huán)一次性遍歷a數(shù)組int, a = new int2, 2, 2 1, 2 , 3, 4, 5,6, 7,8 ;/定義一個2行2列2縱深的3維數(shù)組aforeach(int i in a)Console . WriteLine文溫度(K)。那么不必動系統(tǒng)中成百上千個Temperature屬性,只

4、需在get和set函數(shù)中 稍微修改一下代碼即可:class Thermometer(private double temperature;public Thermometer (double temperature)/構造函數(shù)(this, temperature = temperature;public double Temperature(* 修改后*get return temperature-273.15; set temperature = value+273.15; *修改后* t f f f f f f f建一個控制臺應用程序來測試一下,主函數(shù)為:class Test(static

5、 void Main(string args)(Thermometer a = new Thermometer (40);Console. WriteLine(a. Temperature);Console. WriteLine (首領 A0手舉杯,hand); / / public void Fall()(Console. WriteLine (首領 A 摔杯);)/ / B/ public class B/ /攻擊/ public void Attack()Console. WriteLine (部下 B 發(fā)起攻擊);)/ /部下c/ public class C / / public v

6、oid Attack()Console. WriteLine (部下 C 發(fā)起攻擊);)電至此,三個獨立的類,構造完畢。那么,怎么讓部下B和C,根據(jù)首領的暗語才去相應的行動 呢?我們需要在首領A類中,采用一種方法,把其意圖傳遞出去。在首領A類之前,分別定義一個 帶形參的舉杯委托RaiseEventHandler和一個不帶形參的摔杯委托FallEventHandlero命名 規(guī)那么是在準備傳遞的方法名后加上EventHandle,不要問我為什么,介紹為什么的文章多得是, 大家大可以去查閱。本文的宗旨是,教會大家如何快速的使用委托和事件。當然,你也可以不遵 循此命名規(guī)那么,對程序的運行沒有任何影響

7、,只是會增加自己或他人日后閱讀代碼的難度。delegate void RaiseEventHandler(string hand);delegate void FallEventHandler();然后,在首領A類中,定義兩個事件。這個類似于大家在WinForm中拖放一個Button后,雙 擊該Button,即可編輯其事件。/ summary/首領A舉杯事件 / /summarypublic event RaiseEventHandler RaiseEvent;/ /首領A摔杯事件 / /summarypublic event FailEventHandler FallEvent;好了,做完上

8、面兩個步驟后,就可以在首領A的舉杯和摔杯方法中,調(diào)用上述兩個事件了。這 樣,如果B和C中訂閱該事件,便可自動執(zhí)行了。/ summary/舉杯 / /summary/ 手: 左、右 public void Raise(string hand)(Console. WriteLine (首領 A 0手舉杯,hand);/調(diào)用舉杯事件,傳入左或右手作為參數(shù)if (RaiseEvent!=null)RaiseEvent(hand);/ /摔杯 / public void Fall()Console. WriteLine (首領 A 摔杯); /調(diào)用摔杯事件(FallEvent!=null)FallEve

9、nt ();同樣,不要問為什么這樣寫。按照上述操作即可。一旦用熟這種方法,體會其中含義,自然就明 白為何這么寫了。在部下B和C心中,必須存在首領A,才能執(zhí)行A的暗示吧。所以,在B類和C類中,需要聲 明一個A,該聲明可以通過B和C的構造函數(shù)進行實例化。實例化之后,便可在類B和類C中 訂閱類A的事件了。完整代碼如下:class Programstatic void Main(string args)A a = new A() ; / 定義首領 AB b 二 new B(a) ; / 定義部下 BC c = new C(a) ; / 定義部下 C/首領A左手舉杯a. Raise (左);/首領A右手

10、舉杯/a. Raise(右);/首領A摔杯/a. Fall ();Console. ReadLine();/由于B和C訂閱了 A的事件,所以無需任何代碼,B和C均會按照約定進行動作。)/ summary/首領A舉杯委托/summary/param name二hand手:左、右public delegate voidRaiseEventHandler(string hand);/ summary/首領A摔杯委托/ public delegate voidFallEventHandler();/ /首領A/ public class A/ /首領A舉杯事件/ public event RaiseE

11、ventHandler RaiseEvent;/ /首領A摔杯事件/ public event FallEventHandler FallEvent;/ /舉杯/ / 手: 左、右/param public void Raise(string hand)Console. WriteLine(首領 A0手舉杯,hand); /調(diào)用舉杯事件,傳入左或右手作為參數(shù) if (RaiseEvent!=null)( RaiseEvent(hand);)/ /摔杯/ public void Fall() Console. WriteLine (首領 A 摔杯);/調(diào)用摔杯事件 if (FallEvent!=

12、null) (FallEvent ();)/ /部下B3435363738394041424344454647484950515253545556575859606162636465666768697071727374757677/ /summary public class B78798081828384訂閱舉杯事件 85閱摔杯事件A a;public B(A a)this, a = a;a. RaiseEvent += new RaiseEventHandler (a_RaiseEvent) ; /a. FallEvent += new FailEventHandler (a_FallEv

13、ent); 訂8687888990919293949596979899100101102103104105106107108109110111112 );113114115116117118/ / / /首領舉杯時的動作假設首領A左手舉杯,那么B攻擊void a_RaiseEvent(string hand)if (hand. Equals (左)Attack ();/首領摔杯時的動作void a FallEvent()Attack ();/攻擊public void Attack()Console. WriteLine (部下B發(fā)起攻擊,大喊:猛人張飛來也!/部下C/summarypubli

14、c class C119120121122123124訂閱舉杯事件125閱摔杯事件126127128129130131132133134135136137138139140141142143144145146147148149150151虎生威);152153A a;public C(A a)/ / / /22 NULL,this, a = a;a. RaiseEvent += new RaiseEventHandler (a RaiseEvent) ; /a. FallEvent += new FailEventHandler (a_FallEvent) ; /訂首領舉杯時的動作假設首領A右

15、手舉杯,那么攻擊/paramvoid a_RaiseEvent(string hand)if (hand. Equals (右)Attack (); )/首領摔杯時的動作void a FallEvent()Attack ();/summary 攻擊public void Attack()Console. WriteLine (部下C發(fā)起攻擊,一套落英神掌打得虎String.Empty三者在C#中的區(qū)別(l)NULLnull關鍵字是表示不引用任何對象|的空引用的文字值。null是引用類型變量的默認值。那么也 只有引用型的變量可以為NULL,如果mt i = null,的話,是不可以的,因為Int

16、是值類型的。(2)”和 String.Empty這兩個都是表示空字符串。只不過”“理論上重新開辟內(nèi)存空間,而String.Empty指向一處。 不過優(yōu)化器會優(yōu)化的!string.Empty不分配存儲空間,”“分配一個長度為空的存儲空間,所以一般用string.Empty, 為了以后跨平臺,還是用string.empty。在C#中,大多數(shù)情況下nn和string.Empty可以互換使用。比方:string s =string s2 = string.Empty;if (s = string.Empty) / if 語句成立(3)判定為空字符串的幾種寫法,按照性能從高到低的順序是:s.Length

17、 = 0 優(yōu)于 s = string.Empty 優(yōu)于 s = n注意:1.string strl = 和 string str2=null 的區(qū)別。strl是一個空字符串,空字符串是一個特殊的字符串,只不過這個字符串的值為空,在內(nèi)存中 是有準確的指向的,string str2=null,這樣定義后,只是定義了一個string類的引用,str2并沒有指向任何地方, 在使用前如果不實例化的話,都將報錯。23C#中params關鍵字應用c#params 應用params是C#開發(fā)語言中關鍵字,params主要的用處是在給函數(shù)傳參數(shù)的時候用,就是當函數(shù)的參數(shù) 不固定的時候。在方法聲明中的params

18、關鍵字之后不允許任何其他參數(shù),并且在方法聲明中只允許一 個params關鍵字。關于參數(shù)數(shù)組,需掌握以下幾點。(1)假設形參表中含一個參數(shù)數(shù)組,那么該參數(shù)數(shù)組必須位于形參列表的最后;(2)參數(shù)數(shù)組必須是一維數(shù)組;(3)不允許將params修飾符與ref和out修飾符組合起來使用;(4)與參數(shù)數(shù)組對應的實參可以是同一類型的數(shù)組名,也可以是任意多個與該數(shù)組的元素屬于同一類型的 變量;(5)假設實參是數(shù)組那么按引用傳遞,假設實參是變量或表達式那么按值傳遞。(6)用法:可變的方法參數(shù),也稱數(shù)組型參數(shù),適合于方法的參數(shù)個數(shù)不知的情況,用于傳遞大量的數(shù)組 集合參數(shù);當使用數(shù)組參數(shù)時,可通過使用params關

19、鍵字在形參表中指定多種方法參數(shù),并在方法的參 數(shù)表中指定一個數(shù)組,形式為:方法修飾符返回類型方法名(params類型口 變量名)如帶有參數(shù)的SQL語句,不 同的表的字段數(shù)量也不同,當你更新修改的時候就可以用。例如:params using System;public class MyClasspublic static void UseParams(params int list)for (int i = 0 ; i list.Length; i+ + ) Console.WriteLine(listi); Console.WriteLine();)public static void Use

20、Params2(params object list)for (int i = 0 ; i abstract、override 修飾的方法;不能使用修飾符new static、virtual或abstract來修改override方 法。new. new是派生類用來隱藏基類中的方法的;也就是說在派生類中“看不到”基 類中的方法;.如果要在派生類中隱藏(不是重寫)基類中的方法,而沒有使用new關鍵字, 編譯時會出現(xiàn)一個警告,提示如果是要隱藏基類中的方法,請使用new關鍵字;.派生類可以隱藏基類中的虛方法,也可以隱藏基類中的普通方法。.如果在派生類中用private來修飾new方法,那么只在該派生

21、類中隱藏了基 類中的方法,在該派生類之外,相當于沒有隱藏基類中的方法;.如果在派生類中隱藏了基類中的方法,在該派生類的派生類中,將延續(xù)對該 派生類對基類方法的隱藏。Js的substring和C#的Substring的作用都是從一個字符串中截取出一個子字符串,但它們 的使用方法卻有很大的不同,下邊我們來比擬看看:Js 的 substring語法:程序代碼String.substring(start, end)說明:返回一個從start開始到end(不包含end)的子字符串。例如:程序代碼var str=abcdefgh;document.write(str.substring(0,l);/ret

22、urn: adocument. write(str.substring(2z5);/return :cdedocument. write(str.substring(7,8);/return :hC#的 Substring語法:程序代碼String.Substring(int startindex)String.Substring(int startindex, int length)說明:返回一個從startindex開始到結束的子字符串,或返回一個從startindex開始,長度為length 的子字符串。例如:程序代碼string str = abcdefgh;Response. Wri

23、te(str.Substring(O,l);/return: aResponse. Write(str. Substring(2,3) ;/return:cdeResponse.Write(str.Substring(7zl);/return:hResponse. Write(str. Substring(7);/return :hResponse.Write(str.Substring( 10);/error:startindex 不能大于字符串長度。Response.Write(str.Substring(7,10);error:索引和長度必須引用該字符串內(nèi)的位置。經(jīng)過上邊的說明對它們的使

24、用應該有個比擬清楚的認識了,但對Js的substring還有幾點要說 明:l.start不一定就是第一個參數(shù),end也不一定就是第二個參數(shù),substring。,1)時,開始位置 是L結束位置是3;2.當要返回的子字符串是從開始位置到結束時,end的值必須大于等于字符串的長度,如上邊 的str.substring(7,8),按照索引從。開始算的話end的最大值為九但這邊卻用8,當然, 使用大于8的數(shù)返回的結果也是一樣的,這點比擬有意思。2.0 C#中IndexOf的使用IndexOf()查找字串中指定字符或字串首次出現(xiàn)的位置,返首索引值,如:stLIndexOf(字“);查找字在strl中的索

25、引值(位置)strl.IndexOf(“字串”);查找字串的第一個字符在strl中的索引值(位置)strl.IndexOf(,/start,end); 從 strl 第 start+1 個字符起,查找 end 個字符,查找字 在字符串STR1中的位置從第一個字符算起注意:start+end不能大于strl的長度indexof參數(shù)為string,在字符串中尋找參數(shù)字符串第一次出現(xiàn)的位置并返回該位置。如string s=,0123dfdfdf,;int 1=5,門1縱0代61/);這時 i =4。如果需要更強大的字符串解析功能應該用Regex類,使用正那么表達式對字符串進行匹配。indexof()

26、:在字符串中從前向后定位字符和字符串;所有的返回值都是指在字符串的絕對位 置,如為空那么為-1string test=dsdfjsdfjgkfdsdsfsgfhgjgfjgdddcT;test.indexof(d) =2從前向后定位d第一次出現(xiàn)的位置test.indexof(zd;l) =2從前向后 定位d從第三個字符串第一次出現(xiàn)的位置test.indexof(d,5,2) =6 從前向后 定位d從第5位開始查,查2位,即 從第5位到第7位;lastindexof():在字符串中從后向前定位字符和字符串;、用法和indexof()完全相同。下面介紹 IndexOfAny | |lastinde

27、xofany他們接受字符數(shù)組做為變元,其他方法同上,返回數(shù)組中任何一個字符最早出現(xiàn)的下標位置如下char bbv=,s,/c7b/;string abc = acsdfgdfgchacscdsad;Response.Write(abc.IndexOfAny(bbv) = lResponse.Write(abc.IndexOfAny(bbv, 5)=9Response.Write(abc.IndexOfAny(bbv, 5, 3)=9 lastindexofany 同上。3.0rrnt 的區(qū)別n軟回車:在Windows中表示換行且回到下一行的最開始位置。相當于Mac OS里的r的效 果。在Lin

28、ux、unix中只表示換行,但不會回到下一行的開始位置。r軟空格:在Linux、unix中表示返回到當行的最開始位置。在Mac OS中表示換行且返回到下一行的最開始位置,相當于Windows里的n的 效果。t跳格(移至下一列)。它們在雙引號或定界符表示的字符串中有效,在單引號表示的字符串中無效。rn 一般一起用,用來表示鍵盤上的回車鍵,也可只用n。 t表示鍵盤上的、TAB鍵。就像你使用enter和shift+enter的區(qū)另如果要顯示在頁面上的效果還要轉化為HTML 代碼或用文件中的換行符號:linux,unix: rn windows : n Mac OS : r對應:n LF 或 ASCH

29、 中的 0 x0A(10)r CR 或 ASCII 中的 0 x0D(13)t水平制表符-HT或ASCH中的0 x09 (9)反斜杠$美圓符H雙引號,單引號有關它們的來歷并引起分歧垢原由:”回車(carriage return)和換行(line feed)這兩個概念的來歷和區(qū)別了。 在計算機還沒有出現(xiàn)之前,有一種叫做電傳打字機(Teletype Model 33)的玩意,每秒 鐘可以打10個字符。但是它有一個問題,就是打完一行換行的時候,要用去0.2秒,正好 可以打兩個字符。要是在這02秒里面,又有新的字符傳過來,那么這個字符將喪失。于是,研制人員想了個方法解決這個問題,就是在每行后面加兩個表

30、示結束的字符。一 個叫做回車,告訴打字機把打印頭定位在左邊界;另一個叫做換行,告訴打字機把紙向 下移一行。這就是換行和回車的來歷,從它們的英語名字上也可以看出一二。后來,計算機創(chuàng)造了,這兩個概念也就被般到了計算機上。那時,存儲器很貴,一些科 學家認為在每行結尾加兩個字符太浪費了,加一個就可以。于是,就出現(xiàn)了分歧。Unix系統(tǒng)里,每行結尾只有換行,即n; Windows系統(tǒng)里面,每行結尾是、v 換行,v回車,即、nr; Mac系統(tǒng)里,每行結尾是回車一個直接后果是, Unix/Mac系統(tǒng)下的文件在Windows里翻開的話,所有文字會變成一行;而Windows里 的文件在Unix/Mac下翻開的話,

31、在每行的結尾可能會多出一個八M符號。c語言編程時(windows系統(tǒng))r就是return回到 本行 行首 這就會把這一行以前的輸出覆蓋掉如:int main() cout hahaha r Hxixi;最后只顯示xixi而hahaha背覆蓋了n是回車+換行把光標先移到行首然后換到下一行也就是下一行的行首拉int main() cout hahaha ”rT xixi;那么顯示:hahaha xixi4.0 C# typeof()和 GetType。區(qū)另(J總得來說他們都是為了獲取某個實例具體引用的數(shù)據(jù)類型System.Typeo1、GetType。方法繼承自Object,所以C#中任何對象都具

32、有GetType()方法, x.GetType(),其中x為變量名2、typeof(x)中的x,必須是具體的類名、類型名稱等,不可以是變量名稱3、System.Type.GetTypeO ,有兩個重載方法比方有這樣一個變量i:Int32 i = new Int32();使用GetTypeO , i.GetType。返回值是Int32的類型,但是無法使用typeof(i), 因為i是一個變量,使用typeof(),那么只能:typeof(Int32),返回的同樣是Int32的類型。下面我們具體來看下相關類的介紹:System.Type 類System.Type類定義了很多成員,可以用來檢查某個類

33、型的元數(shù)據(jù),它們返回 的類型大多位于System.Reflection命名空間中。舉例來說,Type.GetMethods() 返回一個Methodinfo類型的數(shù)組,Type.GetFields返回一個Fieldinfo類型的 數(shù)組等。System.Type提供的完整的成員組是很容易擴展的。使用 得到 Type 引用可以用多種方法得到一個Type類的實例。但是,由于Type是一個抽象類,所 以不能直接使用new關鍵字創(chuàng)立一個Type對象。對此我們的首選是:使用 System.Object定義的GetType()方法,它返回一個表示當前對象元數(shù)據(jù)的 Type類的實例:使用一個SportsCar

34、實例得到類型信息SportsCar sc = new SportsCar();Type t = sc.GetType();顯而易見,要想使用這個方法,必須得到類型的編譯時信息(這里是SportsCar 類),并且當前在內(nèi)存中類型實例。使用typeof。得到Type引用另一個取類型信息的方法是使用C# typeof操作符:使用typeof得到類型Type t = typeof(SportsCar);類似,使用typeof操作符,我們不需要建立一個實 例來提取類型信息。但是,仍然需要知道類型的編譯時信息,因為typeof需要 的是類型的強類型名稱,而不是文本表示。使用 。得到 Type 引用為了以

35、更靈活的方式得到類型信息,我們可以調(diào)用System.Type類的靜態(tài)成員 GetTypeO ,然后指定類型的完全限定名。采用這種方法,我們不需要得到正從 中提取元數(shù)據(jù)的類型的編譯時信息,) Type.GetType()方法被重載一:允許我們指定兩個布爾類型的參數(shù),一個用來控制當類型找不到時是否拋出異常, 另一個用來指示是否區(qū)分字符串大小寫。例如:使用靜態(tài)的Type.GetType。方法獲取類型信息(如果SportsCar沒有找到,那么 忽略不拋出異常信息)Type t = Type.GetType(CarLibrary.SportsCar,false,true);) Type.GetType。

36、方法被重載二:在上面的例子中,注意傳入GetTypeO的字符串沒有包含類型所在的程序集信息。 在這種情況下,該類型便被認為是定義在當前執(zhí)行的程序集中。但是,當希望得 到一個外部私有程序集的類型元數(shù)據(jù)時,字符串參數(shù)必須使用類型完全限定名, 加上類型所在的程序集的名字(每一個都用逗號隔開):得到外部程序集中類型的類型信息Type t= Type.GetType(CarLibrary.SportsCarzCarLibrary);例如代碼csharp view plain codvusing System;using System.Reflection;public class Programpubl

37、icint sampleMember;publicvoidSampleMethod() staticvoidMain。(Type t = typeof(Program);也可通過下面這種方式操作./Program obj = new Program();/Type t = obj.GetType();Console.WriteLine(=Methods=);Methodlnfo methodinfo = t.GetMethods();foreach (Methodinfo mlnfo in methodinfo).Console.WriteLine(mInfo.ToString();Conso

38、le.WriteLine(=Members=);Memberlnfo memberinfo = t.GetMembers();foreach (Memberinfo mlnfo in memberinfo).Console. WriteLine(mInfo .ToStringO);Console.ReadLine();)運行結果如下c file:/D:/test/ConsoleApplicati.-蛔=Methods = Uoid SanpleMethodOSystem.String ToStringO Boolean EqualsSysten.Object Int32 GetHashCode

39、 System.Type GetType =Me fibers= Uoid SanpleMethodOSystem.String ToStringO Boo lean EqualsSystem.Object) Int32 GetHashCode System.Type GetType Uoid .ctoi* Int32 sanpleMenberc#接口接口的相關陳述. 一個接口定義了一個契約。.接口可以包容方法、C#屬性、事件、以及索引器。.在一個接口聲明中,我們可以聲明零個或者多個成員。.所有接口成員的默認訪問類型都是public。.如果在接口成員聲明中包括了任何修飾符,那么會產(chǎn)生一個編譯器

40、錯誤。.與一個非抽象類類似,一個抽象類必須提供接口中所有成員的實現(xiàn),只要這些成員在這個類 的基類中出現(xiàn)過。接口的理解1.面向接口編程利用00的一個基本性質-多態(tài),相同方法不同表現(xiàn)??梢赃@樣想一下,client 編寫自己程序的時候,如果直接面向一個具體類寫程序,那這個程序有個風吹草動的,那client 就要受到影響,但如果面向一個接口就不同了,某個具體類變了,只知接口,不知具體類的client 就可以完全不動。都說上層領導比擬好當,因為可以干的事通常對老百姓來說是虛的,越虛就越 不容易錯。這個道理在00中也是適用的。2換個視角看,面向接口編程反映00的另一個方面一封裝,接口將具體實現(xiàn)封裝了起來,

41、可 以不影響客戶的情況下切換實現(xiàn)3.接口的作用,一言以蔽之,就是標志類的類別(type of class)。把不同類型的類歸于不同 的接口,可以更好的管理他們。00的精髓,我以為,是對對象的抽象,最能表達這一點的就是 接口。為什么我們討論設計模式都只針對具備了抽象能力的語言(比方C+ +、java、c#等), 就是因為設計模式所研究的,實際上就是如何合理的去抽象。(cowboy的名言是“抽象就是抽 去像的局部“,看似調(diào)侃,實乃至理)。空接口的使用在接口使用的時候,空接口有2種情況:1.類似于ObjectBuilder中的IBuilderPolicy,他們往往是做一個標記,表示需要某個功能當然

42、你也可以這么用,來表示你的類具有某個功能,實現(xiàn)了你的某個接口.IIIIII Represents a builder policy interface. Since there are no fixed requirementsIII for policies, it acts as a marker interface from which to derive all otherIII policy interfaces.Illpublic interface IBuilderPolicy2 .你的接口繼承了別的接口(非空),你的接口本身沒有聲明函數(shù).這種情況一般是你不希望用戶 使用父接口作

43、為參數(shù)類型,因為他們的用途可能不同,此時就可以用空接口來實現(xiàn).interface Textstring getText();interface SqlText : Text可以看到,Text接口是用于返回一個字符串.而SqlText是一個空接口,它繼承了 Text接口 ,也就 是說SqlText也是一種Text ,但是我們可以知道,任何一個字符串不一定是Sql字符串,所以此時 聲明了一個SqlText接口來用于表名當前的字符串是一個Sql字符串.你的函數(shù)可以這樣聲明:代碼:class A(public virtual void Func () / 注意 virtual,說明這是一個虛擬函 數(shù)C

44、onsole. WriteLine (/zFunc In A);)class B : A /注意B是從A類繼承,所以A是父類,B是子類(public override void Func() / 注意 override,說明重新實現(xiàn)了虛 函數(shù)(Console. WriteLine (,zFunc In B);)class C : B /注意C是從B類繼承,所以B是父類,C是子類()class D : A /注意D是從A類繼承,所以A是父類,D是子類(public new void FuncO /注意new,說明覆蓋父類里的同名類,而 不是重新實現(xiàn)(Console. WriteLine (Z/F

45、unc In D);)class E : D 注意E是從D類繼承,所以D是父類,E是子類 ()class F : A(private new void Func () 注意new關鍵字前有private修飾符,故 該隱藏只在F類內(nèi)有效Console. WriteLine (/zFunc In F); public void doQuery(SqlText sqlText)而不是這樣:public void doQuery(Text text)防止用戶產(chǎn)生歧義的想法,一眼看去,就明白應該傳入一個Sql字符串.接口的成員為什么沒有委托我們都知道C#的接口是可以包含事件的,其實當我們看到事件的時候,

46、很容易就會想到委托, 委托是事件的基礎,如果對委托和事件不是特別清楚的程序員就一定不會明白,為什么C#接口 中可以包含事件而不能有委托呢。其實簡單的說法就是委托也是類型,delegate關鍵字引入的 是一個新的類型,所以一個C#接口無法包容一個委托并把它當作成員;而event關鍵字引入 的是一個新的成員,因此事件可以歸人接口。理解這點,我們要從C#接口的使命說起,C#接 口是一個契約,規(guī)范了接口實現(xiàn)者的行為,而不是要有些什么。很簡單,例如”黨員“是個接口, 它肯定有個動作是“為人民服務“,“某某黨員”實現(xiàn)了“黨員”這個接口,那么“某某黨員“肯定也 要”為人民服務“,至于你”某某黨員“是否必須擁

47、用“電腦”、“小孩”。那么“黨員”這個接口中肯定 不會有規(guī)定。這也就是接口的目的,規(guī)范了實現(xiàn)者的一些行為。所以C#接口的成員都是方法, 不會有其它了。稍有c#常識的程序員都明白,c#中的屬性,其實就是兩個方法,一個Set方 法,一個Get方法,同樣事件和索引器也都是方法,請看下面的接口:public interface IDrawingObjectevent EventHandler OnDraw;string Nameget;set;int thisint indexget;set;void SetValue();該接口包含了 c#接口所能接納的所有成員,事件,屬性,索引器,方法。把該接口編

48、譯后,我 們用MSIL Disassembler工具查看一下: .class interface public abstract auto ansi住 WrapTwoInterfaceEvents .IDrawingObject.custom instance void mscorlibSy stem. Ref lection. DefaultMembSetValue : void()add_OnDraw : void(dass mscorlib5ystem. EventHandler)getjtem : int32(int32)get_Name : string。remove_OnDraw

49、: void(dass mscorlibSystem.EventHandler)setjtem : void(int32Jnt32)set_Name : void(string)OnDraw : mscorlibSystem. EventHandlerItem : instance int32(int32)Name : instance string()這下大家都明白了,其實屬性Name對應于Get_Name(),Set_Name。這兩個方法,事件OnDraw對應于add_OnDraw(),remove_OnDraw()這兩個方法,索引器對應于 get_Item(),set_Item()這兩個

50、方法。在看下面的委托和類的定義:public delegate void TestEventDelegate(object sender, System.EventArgs e);class TestClass public void SetValue()看到了吧,定義一個委托和定義一個類是沒有什么區(qū)別的,都是定義了個新的類型。所以C# 接口是不能有委托的,除非微軟告訴我們C#接口中是可以定義類的。5.0堆和棧堆和棧的區(qū)別可以用如下的比喻來看出:使用棧就象我們?nèi)ワ堭^里吃飯,只管點菜(發(fā)出申請1付錢、和吃(使用),吃飽了 就走,不必理會切菜、洗菜等準備工作和洗碗、刷鍋等掃尾工作,他的好處是快捷,

51、但 是自由度小。使用堆就象是自己動手做喜歡吃的菜肴,比擬麻煩,但是比擬符合自己的口味,而且自由度大。(經(jīng)典!)在計算機領域,堆棧是一個不容忽視的概念,堆棧是兩種數(shù)據(jù)結構。堆棧都是 一種數(shù)據(jù)項按序排列的數(shù)據(jù)結構,只能在一端(稱為棧頂(top)對數(shù)據(jù)項進行插入和 刪除。在單片機應用中,堆棧是個特殊的存儲區(qū),主要功能是暫時存放數(shù)據(jù)和地址, 通常用來保護斷點和現(xiàn)場。要點:堆,隊列優(yōu)先,先進先出(FIFOfirst in first o ut) 0 棧,先進后出(FILOFirst-In/Last-Out)。一般情況下,如果有人把堆棧合起來說,那它的意思是棧,可不是堆。他們之間區(qū)別,對于初學者來說總是混

52、淆不清,筆者自己就是,因而覺得還是有 必要對此稍加整理,最起碼自己在心里也有個概念。能力問題,寫得不好,對此問 題,各IT類的BBS , blog都有寫得很好的,大家可以學習。百度百科上對堆和棧 進行了比照分析:堆棧空間分配棧(操作系統(tǒng)):由操作系統(tǒng)自動分配釋放,存放函數(shù)的參數(shù)值,局部變量的值等。 其操作方式類似于數(shù)據(jù)結構中的棧。堆(操作系統(tǒng)):一般由程序員分配釋放,假設程序員不釋放,程序結束時可能由 OS回收,分配方式倒是類似于鏈表堆棧緩存方式棧使用的是一級緩存,他們通常都是被調(diào)用時處于存儲空間中,調(diào)用完畢立即釋放。 堆那么是存放在二級緩存中,生命周期由虛擬機的垃圾回收算法來決定(并不是一旦

53、 成為孤兒對象就能被回收)。所以調(diào)用這些對象的速度要相對來得低一些。堆棧數(shù)據(jù)結構區(qū)別堆(數(shù)據(jù)結構):堆可以被看成是一棵樹,如:堆排序。棧(數(shù)據(jù)結構):一種先進后出的數(shù)據(jù)結構。例如:順序棧AStack的類定義template class AStack private:int size ; /數(shù)組的規(guī)模T * stackArray ; /存放堆棧元素的數(shù)組int top ; /棧頂所在數(shù)組元素的下標public:AStack ( int MaxStackSize ) / 構造函數(shù) size = MaxStackSize ; stackArray = new T MaxStackSize ; top

54、 = -1 ;)AStack ( ) delete stackArray ; / 析構函數(shù)bool Push ( const T& item ) ; / 向棧頂壓入一個元素bool Pop ( T & item ) ; /從棧頂彈出一個元素bool Peek ( T & item ) const ; / 存取棧頂元素int Is Empty ( void ) const return top =二-1 ; /檢測棧是否為空int IsFull ( void ) const return top size-1 ; /檢測棧是否為滿void clear ( void ) top -1 ; / 清空

55、棧首先,我們舉一個例子:void f() int* p=new int5;這條短短的一句話就包含了堆與棧,看到new ,我們首先就應該想到,我們分 配了一塊堆內(nèi)存,那么指針p呢?他分配的是一塊棧內(nèi)存,所以這句話的意思就是: 在棧內(nèi)存中存放了一個指向一塊堆內(nèi)存的指針p0在程序會先確定在堆中分配內(nèi)存 的大小,然后調(diào)用operator new分配內(nèi)存,然后返回這塊內(nèi)存的首地址,放入棧 中,他在VC6下的匯編代碼如下:00401028 push 14h0040102A call0040102A calloperator new (00401060)0040102F add espz400401032

56、mov00401035 mov00401038 movdword ptr ebp-8,eaxeax;dword ptr ebp-8dword ptr ebp-4,eax這里我們?yōu)榱撕唵尾]有釋放內(nèi)存那么該怎么去釋放呢?是delete p么?澳, 錯了,應該是delete p ,這是為了告訴編譯器:我刪除的是一個數(shù)組,VC6就會 根據(jù)相應的Cookie信息去進行釋放內(nèi)存的工作。好了,我們回到我們的主題:堆和棧究竟有什么區(qū)別?筆者為此做出鄙陋總結主要的區(qū)別由以下幾點:L管理方式不同;2、空間大小不同;3、能否產(chǎn)生碎片不同;4、生長方向不同;5、分配方式不同;6、分配效率不同;管理方式:對于棧來講,

57、是由編譯器自動管理,無需我們手工控制;對于堆來說, 釋放工作由程序員控制,容易產(chǎn)生memory leako空間大?。阂话銇碇v在32位系統(tǒng)下,堆內(nèi)存可以到達4G的空間,從這個角度 來看堆內(nèi)存幾乎是沒有什么限制的。但是對于棧來講,一般都是有一定的空間大小 的,例如,在VC6下面,默認的??臻g大小是1M (好像是,記不清楚了)。當然, 我們可以修改:翻開工程,依次操作菜單如下:Project-Setting-Link ,在Category中選中 Output,然后在Reserve中設定堆棧的最大值和commito注意:reserve最小值為4Byte ; commit是保存在虛擬內(nèi)存的頁文件里面,它

58、設置 的較大會使棧開辟較大的值,可能增加內(nèi)存的開銷和啟動時間。碎片問題:對于堆來講,頻繁的new/delete勢必會造成內(nèi)存空間的不連續(xù),從 而造成大量的碎片,使程序效率降低。對于棧來講,那么不會存在這個問題,因為棧 是先進后出的隊列,他們是如此的一一對應,以至于永遠都不可能有一個內(nèi)存塊從 棧中間彈出,在他彈出之前,在他上面的后進的棧內(nèi)容已經(jīng)被彈出,詳細的可以參 考數(shù)據(jù)結構,這里我們就不再一一討論了。生長方向:對于堆來講,生長方向是向上的,也就是向著內(nèi)存地址增加的方向; 對于棧來講,它的生長方向是向下的,是向著內(nèi)存地址減小的方向增長。分配方式:堆都是動態(tài)分配的,沒有靜態(tài)分配的堆。棧有2種分配方

59、式:靜態(tài)分配和動態(tài)分配。靜態(tài)分配是編譯器完成的,比方局部變量的分配。動態(tài)分配由allo ca函數(shù)進行分配,但是棧的動態(tài)分配和堆是不同的,他的動態(tài)分配是由編譯器進行 釋放,無需我們手工實現(xiàn)。分配效率:棧是機器系統(tǒng)提供的數(shù)據(jù)結構,計算機會在底層對棧提供支持:分 配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執(zhí)行,這就決定了棧的效 率比擬高。堆那么是C/C + +函數(shù)庫提供的,它的機制是很復雜的,例如為了分配一 塊內(nèi)存,庫函數(shù)會按照一定的算法(具體的算法可以參考數(shù)據(jù)結構/操作系統(tǒng))在堆 內(nèi)存中搜索可用的足夠大小的空間,如果沒有足夠大小的空間(可能是由于內(nèi)存碎 片太多),就有可能調(diào)用系統(tǒng)功能去增加

60、程序數(shù)據(jù)段的內(nèi)存空間,這樣就有機會分 到足夠大小的內(nèi)存,然后進行返回。顯然,堆的效率比棧要低得多。從這里我們可以看到,堆和棧相比,由于大量new/delete的使用,容易造成大 量的內(nèi)存碎片;由于沒有專門的系統(tǒng)支持,效率很低;由于可能引發(fā)用戶態(tài)和核心 態(tài)的切換,內(nèi)存的申請,代價變得更加昂貴。所以棧在程序中是應用最廣泛的,就 算是函數(shù)的調(diào)用也利用棧去完成,函數(shù)調(diào)用過程中的參數(shù),返回地址,EBP和局部 變量都采用棧的方式存放。所以,我們推薦大家盡量用棧,而不是用堆。雖然棧有如此眾多的好處,但是由于和堆相比不是那么靈活,有時候分配大量的 內(nèi)存空間,還是用堆好一些。無論是堆還是棧,都要防止越界現(xiàn)象的發(fā)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論