深入理解.net的事件與委托機制

首先介紹一個為什么要在事件中引入委托這個概念:
  事件是對象發送的消息,以發信號通知操作的發生。操作可能是由用戶交互(例如鼠標單擊)引起的,也可能是由某些其他的程序邏輯觸發的。引發事件的對象稱為事件發送方。捕獲事件并對其作出響應的對象叫做事件接收方。

在事件通信中,事件發送方類不知道哪個對象或方法將接收到(處理)它引發的事件。所需要的是在源和接收方之間存在一個媒介(或類似指針的機制)。.NET Framework 定義了一個特殊的類型(Delegate),該類型提供函數指針的功能。

  原理簡介:
  在C#中,一個類可以有域(Fields)、屬性(Properties)、方法(Methods)、索引(Indexs)、事件(Events),以及委托(delegate)等成員,其中事件(Events)成員就是用來聲明一個類事件的。在類中聲明一個事件成員一般采用如下的語法形式:
Public event 代理名 事件名
如在某個類中申明一個MyClick事件成員,其語法如下:
Public event DelegateName(自定義的一個委托) MyClick;

  在C#中,增加了一個新的數據類型delegate(代表)來解決事件處理問題。代表數據類型非常類似于C語言中的指針,其與指針不同的是,其是代碼是安全的,可管理的。這里是DelegateName可以是系統已經提供的代理EventHandler,也可以是自己預先定義好的委托,委托的定義如下:
  Public delegate [返回值] delegatename(委托的名字)(參數列表……..)
(它可以放在類外面,也可以放到類中,只要能在代碼中訪問到即可)
這里注意:如果是這個委托為事件而申明的,這里的返回值的類型就只能是void類型的,否則就要出現問題.

  在C#中,通過使用delegate,你可以通過“+=”(加等于)操作符非常容易地為.Net對象中的一個事件添加一個甚至多個響應方法;還可以通過非常簡單的“-=”(減等于)操作符取消這些響應方法。如下面為temp按鈕添加Click事件的語句:
在上面聲明事件的語句中,Eventhandler是一個delegate(代表)類型,其在.Net類庫中如下聲明的:
  public delegate void EventHandler(object sender,EventArgs e);
這樣,所有形如:void 函婁名(object 參數名,EventArgs 參數名); 的函數都可以作為Control類的Click事件響應方法了。如下面所定義的一個事件響應方法:
private void button1_Click(object sender, System.EventArgs e)
  由于是通過delegate(代表類型)來處理事件,因此,可能通過累加使一個事件具有多個響應方法;與此同時,還可以使一個方法作為多個事件的響應方法。(注意:在C#語言類中的event成員后面只能出現“+=”與“-=”兩個表示添加與取消事件響應函數的操作符。)

  不管是ASP.Net還是一般的Windows Forms 編程,在C#中,基本上我們遇到的事件響應方法都是說明成如下的形式:
private void button1_Click(object sender, System.EventArgs e)
(參考其他資料)

  一個事件響應方法的存取權限、返回值類型、參數及類型甚至方法名稱等是否都必須固定不變呢?答案是:不是!

  一般情況下,事件的響應方法中都有兩個參數,其中一個代表引發事件的對象即sender,由于引發事件的對象不可預知的,因此我們把其聲明成為object類型,所有的對象都適用。第二個參數代表引發事件的具體信息,各種類型的事件中可能不同,這要根據類中事件成員的說明決定。

  我們知道,事件是通過delegate(代表) 來處理的。假設將要表示事件的代表說明成如下形式:
delegate int MyEventHandler(object sender, ToolBarButtonClickEventArgs e);
則當涉及上面的事件響應函數聲明時,就須要聲明成如下的形式:
private int MyTest(object sender,ToolBarButtonClickEventArgs e)
{
}
在給對象添加事件響應方法時就可以用如下的代碼實現:
Control.Event+=new MyEventHandler(MyTest);

  下面是我根據對委托的理解,自己編寫的代碼,
  注意目的是為了深入理解事件是怎樣和委托結合的。我的想法是這樣的:既然microsft已經為button按鈕寫了onclick事件了(不傳遞任何參數進入事件),我就打算重新添加一個MyClick事件,當 按鈕的onclick事件發生的時候,我就重寫默認的onclick事件,執行自己添加的MyClick事件,并傳遞參數進入事件(MyClick)中進行處理。

  首先添加一個自定義的按鈕MyButton,它繼承于System.Window.Forms.Button類的.代碼如下:
namespace ExampleAddEventForm
{
public delegate void MyDelegate(object sender,object myevenargs); //這里把申明委托放到了類外,其實放到類中也一樣,只是引用地址不同而已。
 public class MyButton:System.Windows.Forms.Button
 {
 protected override void OnClick(EventArgs e)
 {//重寫默認的onclick方法,觸發自己的事件
  TriggerEvent();
 }
 public event MyDelegate MyDelegateEvent; //申明一個事件
 public void TriggerEvent()
 {
 if (MyDelegateEvent != null)
 {
 MyEvenArgs myevenargs = new MyEvenArgs();
 myevenargs.FirstName = "cc";
 myevenargs.LastName = "changchang";
 MyDelegateEvent(this,myevenargs);
 }
 }
 }
}

  上面的MyEvenArgs類是我自定義的類,它繼承與系統提供的System.EvenArgs類注意目的是為了傳入參數進入方法。
Namespace ExampleAddEventForm
{
 class MyEvenArgs:System.EventArgs
 {
 private string firstname;
 public string FirstName
 {
 get { return firstname; }
 set { firstname = value; }
 }
 private string lastname;
 public string LastName
 {
 get { return lastname; }
 set { lastname = value; }
 }
 }
}
  到現在為止,我們已經實現了自己的按鈕(自定義了事件和委托,并重寫了microsft為我們提供的onclick事件,執行我們的OnClick事件)和Onclick事件中需要的傳遞參數的MyEvenArgs類

  下面就把我們寫的MyButton按鈕放到頁面上(不是拖放到頁面上,這是不可能的),我們至少都要在InitializeComponent方法中加載到頁面上
private MyButton mybutton
private void InitializeComponent()
{
 this.mybutton = new MyButton();
 this.SuspendLayout();
 this.mybutton.Location = new System.Drawing.Point(71, 99);
 this.mybutton.Name = "mybutton";
 this.mybutton.Size = new System.Drawing.Size(150, 23);
 this.mybutton.TabIndex = 0;
 this.mybutton.Text = "Override Button";
 this.mybutton.UseVisualStyleBackColor = true;
 this.mybutton.MyDelegateEvent += new.MyDelegate(this.MyButton_Click);
 this.Controls.Add(mybutton);
}

  這時回到設計界面提示錯誤(這是正常的)(沒有刷新)。從這里可以看到
mybutton.MyDelegateEvent += new MyDelegate(MyButton_Click);
這句話就是注冊事件,用自定義button中事件執行MyButton_Click函數方法,其實這就是事件處理程序。

  返回到后臺代碼的如下:(這里只是簡單的提示有用的消息) public void MyButton_Click(object sender, MyEvenArgs message)
 {
 MessageBox.Show(message.FirstName+message.LastName); //這個就是傳遞個事件處理程序中的參數
  MessageBox.Show("this is a custom button's click!");
}
  現在代碼就結束了,運行程序就彈出“this is a custom button’s click”的提示.

轉載于:https://www.cnblogs.com/horse/archive/2010/02/20/1669629.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/379377.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/379377.shtml
英文地址,請注明出處:http://en.pswp.cn/news/379377.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java ObjectOutputStream flush()方法與示例

ObjectOutputStream類flush()方法 (ObjectOutputStream Class flush() method) flush() method is available in java.io package. flush()方法在java.io包中可用。 flush() method is used to flush this stream and write bytes immediately of any buffered output to the u…

ffmpeg 命令裁剪合并

1 mp4格式: 裁剪從一個視頻中的1分鐘、2分鐘、3分鐘開始截取10秒 ffmpeg -i test_1280x720.mp4 -ss 00:01:00 -t 10 -codec copy copy1.mp4 ffmpeg -i test_1280x720.mp4 -ss 00:02:00 -t 10 -codec copy copy2.mp4 ffmpeg -i test_1280x720.mp4 -ss 00:03:00 -t 10…

Struts2初始化流程及源碼分析

1.1 Struts2初始化 在講Struts2的初始化之前,應該為大家描述下Web應用中的過濾器Filter,這關系到我們對核心過濾器FilterDispatcher的正確理解。 Filter:一個filter是一個對象,為每個請求資源(一個servlet或靜態內容) &#xff0c…

實驗1 數據庫操作

實驗1 數據庫操作一、實驗目的 1.掌握管理工具、T-SQL創建數據庫的方法。 2.掌握管理工具、T-SQL修改和查看數據庫的方法。 3.掌握管理工具、T-SQL刪除數據庫的方法。 4.掌握數據庫的附加與分離 二、實驗要求 1.創建實驗所用到的“網上購物系統”數據庫eshop。 三、實驗內容 1…

Java FileInputStream finalize()方法與示例

FileInputStream類的finalize()方法 (FileInputStream Class finalize() method) finalize() method is available in java.io package. finalize()方法在java.io包中可用。 finalize() method is used to assure that close() method of this FileInputStream invokes when th…

逆風飛揚,吳仁宏

摘自逆風飛揚,吳仁宏自傳 它是一個從"生而自卑"到"個性飛揚"的故事,當然具有傳奇色彩 中國人幾千年都不是天生的贏家,讓我們努力,為國為家為自己,做贏家! 生存哲學 尼采 痛苦,挫折使生命遷長,使人…

ffmpeg 命令圖片和視頻相互轉換

1當前文件環境: ffmpeg -i test.mp4 -y -f image2 -ss 00:00:02 -vframes 1 -s 640x360 test.jpg ffmpeg -i test.mp4 -y -f image2 -ss 00:00:02 -vframes 1 -s 640x360 test.bmp 使用ffplay test.jpb ffplay test.bmp 都是可以打開的 參數介紹: -y 如…

如何點擊鏈接直接跳轉到app store指定應用下載頁面

轉載自:http://blog.csdn.net/zengconggen/article/details/6789420 NSString *str [NSString stringWithFormat:"http://itunes.apple.com/us/app/id%d", 436957167]; [[UIApplication sharedApplication] openURL:[NSURL urlWithString:str]];其中&…

COLLEGE.sql(復制的時候注意路徑!!!)

USE [master] GO /****** Object: Database [COLLEGE] Script Date: 2019/11/25 星期一 上午 08:57:11 / CREATE DATABASE [COLLEGE] ON PRIMARY ( NAME N’COLLEGE_m’, FILENAME N’F:\COLLEGE\COLLEGE.mdf’ , SIZE 51200KB , MAXSIZE UNLIMITED, FILEGROWTH 10240KB )…

【管理】「本能叛逆」與「理性叛逆」

叛逆是一般人認知的負面名詞,但是,很多人都忽略掉,它卻是人類進步的重要因子。觀察孩童的成長過程,十歲以后都會出現叛逆行為,相當令父母及師長頭痛。然而,叛逆卻是促使孩童突破家庭單一環境養成的認知與觀…

Java Double類parseDouble()方法的示例

Double類parseDouble()方法 (Double class parseDouble() method) parseDouble() method is available in java.lang package. parseDouble()方法在java.lang包中可用。 parseDouble() method is used to return the double value corresponding to the given String or in oth…

ffmpeg命令 拉流

1: 拉流播放:rtmp (ffplay rtmp://server/live/streamName) ffplay -x 480 -y 320 rtmp://58.200.131.2:1935/livetv/cctv1 2: 拉流存儲到文件:rtmp ffmpeg -i rtmp://58.200.131.2:1935/livetv/cctv1 -codec copy cctvrtmp.f…

小心pthread_cond_signal和SetEvent之間的差異

ZZ FROM: http://blog.csdn.net/absurd/article/details/1402433 轉載時請注明出處和作者聯系方式&#xff1a;http://blog.csdn.net/absurd 作者聯系方式&#xff1a;Li XianJing <xianjimli at hotmail dot com> 更新時間&#xff1a;2006-12-19 今天幫同事查一個多線…

eshop.sql(復制的時候注意路徑!!!)

USE [master] GO /****** Object: Database [eshop] Script Date: 2019/11/25 星期一 上午 08:54:14 / CREATE DATABASE [eshop] ON PRIMARY ( NAME N’eshop_dat’, FILENAME N’D:\eshop\eshop_dat.mdf’ , SIZE 10240KB , MAXSIZE 51200KB , FILEGROWTH 5120KB ) LOG O…

doublevalue_Java Double類doubleValue()方法與示例

doublevalueDouble類doubleValue()方法 (Double class doubleValue() method) doubleValue() method is available in java.lang package. doubleValue()方法在java.lang包中可用。 doubleValue() method is used to return the value denoted by this Double object converted…

ffmpeg 命令過濾器裁剪

1 圖片操作&#xff1a; 原圖&#xff1a; 使用ffplay 顯示左半邊 ffplay -i input.png -vf cropiw/2:ih:0:0 可以通過ffmpeg 保存 ffmpeg -i input.png -vf cropiw/2:ih:0:0 out.png 2 視頻操作&#xff1a; 原視頻&#xff1a; 顯示左半邊 ffplay -i cctvhttp.flv -vf …

去除aspx生成的頁面最開始的空行

使用.aspx生成的頁面一般都會有一個或多個空行&#xff0c;當然這些空行不會影響頁面在瀏覽器中的渲染結果&#xff0c;不過在查看源代碼的時候感覺有些別扭&#xff0c;我曾試著去刪除這些空行&#xff0c;但沒有成功&#xff0c;你知道你們有沒有去嘗試。 1 <% Page Langu…

PUBLISH.sql(復制的時候注意路徑!!!)

USE [master] – GO – /****** Object: Database [PUBLISH] Script Date: 2019/11/25 星期一 上午 09:00:04 / – CREATE DATABASE [PUBLISH] ON PRIMARY – ( NAME N’PUBLISH’, FILENAME N’F:\PUBLISH\PUBLISH.mdf’ , SIZE 51200KB , MAXSIZE UNLIMITED, FILEGROWTH …

c ++ 函數的esp指針_在C ++中通過指針訪問成員函數

c 函數的esp指針Create a class along with data member and member functions and then access the member functions by using a pointer in C. 創建一個類以及數據成員和成員函數&#xff0c;然后使用C 中的指針訪問成員函數。 如何通過指針訪問成員函數&#xff1f; (How…

[iphone-cocos2d]分享一段Objective-C可調用的游戲中播放音樂(1)

首先需要引入AudioTool 這個framework 代碼 -(id)initWithPath:(NSString *)path{ UInt32 size, maxPacketSize; char*cookie; inti; if(gThereIsAnActiveTrack) { NSLog("*** WARNING *** GBMusicTrack only plays one track at a time…