欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#委托與事件初探

 更新時間:2016年02月14日 11:14:05   作者:Koala''s_Dream  
事件是委托的一種特殊形式,當(dāng)發(fā)生有意義的事情時,事件處理對象通知過程。接下來通過本文給大家介紹C#委托與事件初探,感興趣的朋友一起學(xué)習(xí)吧

委托給了C#操作函數(shù)的靈活性,我們可使用委托像操作變量一樣來操作函數(shù),其實這個功能并不是C#的首創(chuàng),早在C++時代就有函數(shù)指針這一說法,而在我看來委托就是C#的函數(shù)指針,首先先簡要的介紹一下委托的基本知識:

委托的定義

委托的聲明原型是

delegate <函數(shù)返回類型> <委托名> (<函數(shù)參數(shù)>)

例子:public delegate void CheckDelegate(int number);//定義了一個委托CheckDelegate,它可以注冊返回void類型且有一個int作為參數(shù)的函數(shù)

這樣就定義了一個委托,但是委托在.net內(nèi)相當(dāng)于聲明了一個類(在后面的代碼中會講到確實如此),類如果不實例化為對象,很多功能是沒有辦法使用的,委托也是如此.

委托的實例化

委托實例化的原型是

<委托類型> <實例化名>=new <委托類型>(<注冊函數(shù)>)

例子:CheckDelegate _checkDelegate=new CheckDelegate(CheckMod);//用函數(shù)CheckMod實例化上面的CheckDelegate 委托為_checkDelegate

在.net 2.0開始可以直接用匹配的函數(shù)實例化委托:

<委托類型> <實例化名>=<注冊函數(shù)>

例子:CheckDelegate _checkDelegate=CheckMod;//用函數(shù)CheckMod實例化上面的CheckDelegate 委托為_checkDelegate
現(xiàn)在我們就可以像使用函數(shù)一樣來使用委托了,在上面的例子中現(xiàn)在執(zhí)行_checkDelegate()就等同于執(zhí)行CheckMod(),最關(guān)鍵的是現(xiàn)在函數(shù)CheckMod相當(dāng)于放在了變量當(dāng)中,它可以傳遞給其它的CheckDelegate引用對象,而且可以作為函數(shù)參數(shù)傳遞到其他函數(shù)內(nèi),也可以作為函數(shù)的返回類型

事件是委托的一種特殊形式,當(dāng)發(fā)生有意義的事情時,事件處理對象通知過程。

一.C語言中的函數(shù)指針

  想要理解什么是委托,就要先理解函數(shù)指針的概念。所謂函數(shù)指針,就是指向函數(shù)的指針(等于沒說-.-)。比如我定義了兩個函數(shù)square和cube分別用于計算一個數(shù)的平方和立方,我再定義函數(shù)指針calcu,然后我讓calcu指向square,那么調(diào)用calcu時就相當(dāng)于調(diào)用了square函數(shù)(注意,此處函數(shù)指針接受的參數(shù)類型及個數(shù)要與函數(shù)一致)。很好理解吧?不多說,上代碼。

#include <stdio.h>
void square(int x) { printf("square of %d is %d\n",x,x*x); }
void cube(int x) { printf("cube of %d is %d\n",x,x*x*x); }
int main()
{
void (*calcu)(int x);
calcu=square;
calcu();
return ;
}

二.C#中委托的實質(zhì)

  委托又名委托類型,為什么C#弄出這個東西?因為C#是一門比較安全的語言,不允許操作指針,于是我們不能定義函數(shù)指針。但想要達到相同的效果,于是定義了委托類型。所謂委托類型,其本質(zhì)就是C中的指針類型。于是代碼變成了這樣:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Delegate
{
class Program
{
static void square(int x) { Console.WriteLine("square of {} is {}", x, x * x); }
static void cube(int x) { Console.WriteLine("cube of {} is {}", x, x * x * x); }
delegate void math(int x); //定義委托類型
static void Main(string[] args)
{
math calcu;
calcu += square;
calcu();
Console.ReadKey();
}
}
} 

  可以看出,定義委托類型math實際上就相當(dāng)于定義了void*類型。而委托類型實例化得到的calcu實際上就是函數(shù)指針。(說句題外話:定義函數(shù)(方法)時要加上static是因為調(diào)用函數(shù)時并未實例化,只有靜態(tài)方法能夠直接通過類調(diào)用)。

三.委托的使用方法

  我們在上述代碼19行后面加上一行代碼 calcu+=cube; 運行會發(fā)現(xiàn),square和cube均被調(diào)用??梢钥闯?,符號 += 表示綁定方法到委托變量,同理符號 -= 表示取消綁定??梢岳斫鉃閏alcu是void **類型,即它指向了一個數(shù)組,數(shù)組中的每一項都是函數(shù)指針類型,每次調(diào)用calcu時,遍歷此數(shù)組,即依次調(diào)用每個綁定的方法。

四.封裝與事件的引入

  下面我們要用面向?qū)ο蟮乃枷雽⑸鲜龃a進行封裝,使其變清晰。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Delegate
{
public delegate void math(int x);
public class Calcu
{
public math calcu;
}
class Program
{
static void square(int x) { Console.WriteLine("square of {} is {}", x, x * x); }
static void cube(int x) { Console.WriteLine("cube of {} is {}", x, x * x * x); }
static void Main(string[] args)
{
Calcu c = new Calcu();
c.calcu += square;
c.calcu += cube;
c.calcu();
Console.ReadKey();
}
}
}

由于委托變量是public的,封裝的程度很低,在外部可以任意修改。為了改進這個問題,C#引入了事件。

  所謂事件,實際上還是委托的實例化,只是其內(nèi)部多了一些定義,多了一些限制。其一,事件實際上聲明了一個private類型的委托變量,因此在類外無法直接調(diào)用。

  于是我們將上述代碼的第12行改成這樣:

public event math calcu;

  運行之后25行報錯了,因為calcu是private的,不能直接調(diào)用。但23,24行并沒有報錯。那么問題來了,為什么我們可以用+=來給calcu綁定方法呢?

  因為其二,事件還幫我們干了一件事情,就是定義了綁定方法和取消綁定方法的函數(shù),它們是public的,并且將運算符+=,-=重載,和這兩個函數(shù)對應(yīng)。

  好了,現(xiàn)在我們要寫一個接口函數(shù)來完成計算:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Delegate
{
public delegate void math(int x);
public class Calcu
{
public event math calcu;
public void calculate(int x)
{
calcu(x);
}
}
class Program
{
static void square(int x) { Console.WriteLine("square of {} is {}", x, x * x); }
static void cube(int x) { Console.WriteLine("cube of {} is {}", x, x * x * x); }
static void Main(string[] args)
{
Calcu c = new Calcu();
c.calcu += square;
c.calcu += cube;
c.calculate();
Console.ReadKey();
}
}
}

  至此,基本概念已經(jīng)清晰。

  想來,使用事件會讓人不得不將對象封裝起來,這應(yīng)該就是面向?qū)ο笏枷氲捏w現(xiàn)吧。

以上內(nèi)容是針對C#委托與事件初探的相關(guān)知識,希望對大家有所幫助。

相關(guān)文章

  • C# 關(guān)于LoadLibrary的疑問詳解

    C# 關(guān)于LoadLibrary的疑問詳解

    這篇文章主要介紹了C# 關(guān)于LoadLibrary的疑問詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • C# 獲取系統(tǒng)進程的用戶名

    C# 獲取系統(tǒng)進程的用戶名

    這也是應(yīng)一位網(wǎng)友的要求寫的,寫的比較倉促,湊合吧
    2009-06-06
  • C#調(diào)用dll報錯:無法加載dll,找不到指定模塊的解決

    C#調(diào)用dll報錯:無法加載dll,找不到指定模塊的解決

    這篇文章主要介紹了C#調(diào)用dll報錯:無法加載dll,找不到指定模塊的解決問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • 深入理解c#多態(tài)

    深入理解c#多態(tài)

    這篇文章主要介紹了c#多態(tài)的相關(guān)知識,文中代碼非常詳細,幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • 聊聊Unity 自定義日志保存的問題

    聊聊Unity 自定義日志保存的問題

    這篇文章主要介紹了Unity 自定義日志保存的問題,之前unity5.x在代碼中寫了debug.log打包之后在當(dāng)前程序文件夾下會有個對應(yīng)的"outlog.txt",后來進行了更改,今天通過代碼給大家介紹了Unity日志保存的問題,需要的朋友一起看看吧
    2021-05-05
  • C#在MEF框架中實現(xiàn)延遲加載部件

    C#在MEF框架中實現(xiàn)延遲加載部件

    這篇文章介紹了C#在MEF框架中實現(xiàn)延遲加載部件的方法,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • C#特性-迭代器(上)及一些研究過程中的副產(chǎn)品

    C#特性-迭代器(上)及一些研究過程中的副產(chǎn)品

    這篇文章主要介紹了C#特性-迭代器(上)及一些研究過程中的副產(chǎn)品,需要的朋友可以參考下
    2014-12-12
  • C#采用mouse_event函數(shù)實現(xiàn)模擬鼠標功能

    C#采用mouse_event函數(shù)實現(xiàn)模擬鼠標功能

    這篇文章主要介紹了C#模擬鼠標點擊小功能,通過代碼向大家做分析,需要的朋友可以參考下
    2015-07-07
  • C#二維數(shù)組與多維數(shù)組的具體使用

    C#二維數(shù)組與多維數(shù)組的具體使用

    本文主要介紹了C#二維數(shù)組與多維數(shù)組的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • C#中的let字句應(yīng)用示例

    C#中的let字句應(yīng)用示例

    這篇文章主要給大家介紹了C#中的let字句,文中通過應(yīng)用實例介紹的很詳細,相信對大家具有一定的參考價值,有需要的朋友們下面來一起看看吧。
    2017-02-02

最新評論