




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
委托和事件
委托基本概念
委托,顧名思義,就是中間代理人的意思。通俗地說,委托是一個可以引用方法的類型,當你創建一個委托,也就創建了一個引用方法的對象,進而就可以調用那個方法,即是說委托可以調用它所指向的方法。實際委托和C++函數指針很類似,但具有更高的安全性。而且委托引用的方法可以改變,這樣同一個委托就可以調用多個不同的方法。委托類型派生自.NETFramework中的Delegate
類。委托類型是密封的,不能從Delegate中派生委托類型,也不可能從中派生自定義類。
C#中委托的具體的步驟是:
(1)聲明一個委托,其參數形式一定要和想要包含的方法的參數形式一致。
(2)定義所有你要定義的方法,其參數形式和第一步中聲明的委托對象的參數形式必須相同。
(3)創建委托對象并將所希望的方法包含在該委托對象中。
(4)通過委托對象調用包含在其中的各個方法。
步驟1:聲明一個委托
格式:
[修飾符]delegate返回類型委托名(參數列表);
例:
publicdelegatevoidMyDelegate1(stringinput);
publicdelegatedoubleMyDelegate2();
聲明一個委托的對象,與聲明一個普通類對象的方式一樣:委托名委托對象名;例:MyDelegate1a;MyDelegate2b;步驟2:定義方法,其參數形式和步驟1中聲明的委托對象的必須相同
classMyClass1{
publicvoiddMethod1(stringinput){
Console.WriteLine(“Method1傳遞的參數是{0}",input);
}
publicvoiddMethod2(stringinput){
Console.WriteLine(Method1傳遞的參數是{0}",input);}
}
步驟3:創建一個委托對象并將上面的方法包含其中
例:
MyClass1c2=newMyClass1();MyDelegate1d1;d1=newMyDelegate1(c2.dMethod1);MyDelegate1d2=newMyDelegate1(c2.dMethod2);
步驟4:通過委托對象調用包含在其中的方法
例:
d1("abc");d2("123");下面這個例子就是將上面的4個步驟合在一起:usingSystem;publicdelegatevoidMyDelegate1(stringinput);classMyClass1{
publicvoiddMethod1(stringinput)
{
Console.WriteLine("dMethod1傳遞的參數是{0}",input);?
}publicvoiddMethod2(stringinput)
{
Console.WriteLine("dMethod2傳遞的參數是{0}",input);
} }classDriver{
staticvoidMain(){
MyClass1c2=newMyClass1();?
MyDelegate1d1=newMyDelegate1(c2.dMethod1);?
MyDelegate1d2=newMyDelegate1(c2.dMethod2);?
d1("abc");
d2("123");
}
}泛型我們在編寫程序時,經常遇到兩個模塊的功能非常相似,只是一個是處理int數據,另一個是處理string數據,或者其他自定義的數據類型,但我們沒有辦法,只能分別寫多個方法處理每個數據類型,因為方法的參數類型不同。有沒有一種辦法,在方法中傳入通用的數據類型,這樣不就可以合并代碼了嗎?泛型的出現就是專門解決這個問題的。泛型簡介泛型是C#2.0的最強大的功能。通過泛型可以定義類型安全的數據結構,而無須使用實際的數據類型。這能夠顯著提高性能并得到更高質量的代碼,因為您可以重用數據處理算法,而無須復制類型特定的代碼。在概念上,泛型類似于C++
模板,但是在實現和功能方面存在明顯差異。本文討論泛型處理的問題空間、它們的實現方式、該編程模型的好處,以及獨特的創新(例如,約束、一般方法以及一般繼承)。您還將了解在.NETFramework的其他領域(例如,反射、數組、集合、序列化和遠程處理)中如何利用泛型,以及如何在所提供的基本功能的基礎上進行改進。C#泛型演示我們先看下面的代碼,代碼省略了一些內容,但功能是實現一個棧,這個棧只能處理int數據類型:publicclassStack
{
privateint[]m_item;
publicintPop(){...}
publicvoidPush(intitem){...}
publicStack(inti)
{
this.m_item=newint[i];
}
}上面代碼運行的很好,但是,當我們需要一個棧來保存string類型時,該怎么辦呢?很多人都會想到把上面的代碼復制一份,把int改成string不就行了。當然,這樣做本身是沒有任何問題的,但一個優秀的程序是不會這樣做的,因為他想到若以后再需要long、Node類型的棧該怎樣做呢?還要再復制嗎?優秀的程序員會想到用一個通用的數據類型object來實現這個棧:publicclassStack
{
privateobject[]m_item;
publicobjectPop(){...}
publicvoidPush(objectitem){...}
publicStack(inti)
{
this.m_item=new[i];
}}這個棧寫的不錯,他非常靈活,可以接收任何數據類型,可以說是一勞永逸。但也不是沒有缺陷的,主要表現在:當Stack處理值類型時,會出現裝箱、折箱操作,這將在托管堆上分配和回收大量的變量,若數據量大,則性能損失非常嚴重。
在處理引用類型時,雖然沒有裝箱和折箱操作,但將用到數據類型的強制轉換操作,增加處理器的負擔。在數據類型的強制轉換上還有更嚴重的問題(假設stack是Stack的一個實例):Node1x=newNode1();
stack.Push(x);
Node2y=(Node2)stack.Pop();上面的代碼在編譯時是完全沒問題的,但由于Push了一個Node1類型的數據,但在Pop時卻要求轉換為Node2類型,這將出現程序運行時的類型轉換異常,但卻逃離了編譯器的檢查。針對object類型棧的問題,我們引入泛型,他可以優雅地解決這些問題。泛型用用一個通過的數據類型T來代替object,在類實例化時指定T的類型,運行時(Runtime)自動編譯為本地代碼,運行效率和代碼質量都有很大提高,并且保證數據類型安全。使用泛型
下面是用泛型來重寫上面的棧,用一個通用的數據類型T來作為一個占位符,等待在實例化時用一個實際的類型來代替。讓我們來看看泛型的威力:publicclassStack<T>
{
privateT[]m_item;
publicTPop(){...}
publicvoidPush(Titem){...}
publicStack(inti)
{
this.m_item=newT[i];
}
}類的寫法不變,只是引入了通用數據類型T就可以適用于任何數據類型,并且類型安全的。這個類的調用方法:實例化只能保存int類型的類Stack<int>a=newStack<int>(100);
a.Push(10);
a.Push("8888");//這一行編譯不通過,因為類a只接收int類型的數據
intx=a.Pop();實例化只能保存string類型的類Stack<string>b=newStack<string>(100);
b.Push(10);//這一行編譯不通過,因為類b只接收string類型的數據
b.Push("8888");
stringy=b.Pop();泛型類和object實現的類的區別他是類型安全的。實例化了int類型的棧,就不能處理string類型的數據,其他數據類型也一樣。無需裝箱和折箱。這個類在實例化時,按照所傳入的數據類型生成本地代碼,本地代碼數據類型已確定,所以無需裝箱和折箱。無需類型轉換。泛型概述使用泛型類型可以最大限度地重用代碼、保護類型的安全以及提高性能。泛型最常見的用途是創建集合類。.NETFramework類庫在System.Collections.Generic命名空間中包含幾個新的泛型集合類。應盡可能地使用這些類來代替普通的類,如System.Collections命名空間中的ArrayList。您可以創建自己的泛型接口、泛型類、泛型方法、泛型事件和泛型委托。可以對泛型類進行約束以訪問特定數據類型的方法。關于泛型數據類型中使用的類型的信息可在運行時通過反射獲取。泛型類如何實例化C#泛型類在編譯時,先生成中間代碼IL,通用類型T只是一個占位符。在實例化類時,根據用戶指定的數據類型代替T并由即時編譯器(JIT)生成本地代碼,這個本地代碼中已經使用了實際的數據類型,等同于用實際類型寫的類,所以不同的封閉類的本地代碼是不一樣的泛型類中數據類型的約束
程序員在編寫泛型類時,總是會對通用數據類型T進行有意或無意地有假想,也就是說這個T一般來說是不能適應所有類型,但怎樣限制調用者傳入的數據類型呢?這就需要對傳入的數據類型進行約束,約束的方式是指定T的祖先,即繼承的接口或類。因為C#的單根繼承性,所以約束可以有多個接口,但最多只能有一個類,并且類必須在接口之前。這時就用到了C#2.0的新增關鍵字where:publicclassNode<T,V>whereT:Stack,IComparable
whereV:Stack
{...}以上的泛型類的約束表明,T必須是從Stack和IComparable繼承,V必須是Stack或從Stack繼承,否則將無法通過編譯器的類型檢查,編譯失敗。泛型方法
泛型不僅能作用在類上,也可單獨用在類的方法上,他可根據方法參數的類型自動適應各種參數,這樣的方法叫泛型方法。看下面的類:publicclassStack2
{
publicvoidPush<T>(Stack<T>s,paramsT[]p)
{
foreach(Ttinp)
{
s.Push(t);
}
}
}原來的類Stack一次只能Push一個數據,這個類Stack2擴展了Stack的功能(當然也可以直接寫在Stack中),他可以一次把多個數據壓入Stack中。其中Push是一個泛型方法,這個方法的調用示例如下:Stack<int>x=newStack<int>(100);
Stack2x2=newStack2();
x2.Push(x,1,2,3,4,6);
strings="";
for(inti=0;i<5;i++)
{
s+=x.Pop().ToString();
}//至此,s的值為64321泛型中的靜態成員變量
在C#1.x中,我們知道類的靜態成員變量在不同的類實例間是共享的,并且他是通過類名訪問的。C#2.0中由于引進了泛型,導致靜態成員變量的機制出現了一些變化:靜態成員變量在相同封閉類間共享,不同的封閉類間不共享。這也非常容易理解,因為不同的封閉類雖然有相同的類名稱,但由于分別傳入了不同的數據類型,他們是完全不同的類,比如:Stack<int>a=newStack<int>();
Stack<int>b=newStack<int>();
Stack<long>c=newStack<long>();類實例a和b是
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 福利院新生兒喂養
- 社區居家養老優化策略
- 淄博旅游投資機會
- Salfredin-A7-生命科學試劑-MCE
- 機器人輔助手術在泌尿科的應用
- 2025年分級診療背景下遠程醫療服務患者需求與偏好研究報告
- 2025年教育信息化基礎設施在教育信息化項目中的創新與應用報告
- 食品飲料企業數字化營銷與電商運營效果評估體系研究報告
- 餐飲行業供應鏈整合與2025年成本控制技術創新報告
- 互聯網醫療2025年醫藥電商平臺合規監管與市場布局分析報告
- 有限空間作業及應急物資清單
- DB13(J)∕T 8060-2019 城鎮供熱管道及設備安裝工程施工質量驗收標準
- 《國際商務》課程
- 壓力容器設計管理制度
- 比亞迪員工手冊54
- 國際經濟學期末考試試題庫含答案
- 應力波理論復習資料
- 基于PLC的音樂噴泉控制系統的設計-畢業設計
- 體育場地與設施
- 五年級部編版語文下學期修改病句專項強化練習題
- 民辦非企業單位清算報告
評論
0/150
提交評論