日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

深刻理解:C#中的委托、事件

發布時間:2023/12/4 C# 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深刻理解:C#中的委托、事件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

C#中的事件還真是有點繞啊,以前用JavaScript的我,理解起來還真是廢了好大勁!剛開始還真有點想不明白為什么這么繞,想想和JS的區別,最后終于恍然大悟!

C#中事件繞的根本原因:

  • C#的方法,它不是一個類型,它只是其它類型的成員;

  • C#是一個強類型的語言,定義方法時,它的參數必須指定類型,如public void add(int n){...};

  • 所以,一個方法不能直接作為其它方法的參數,把一個方法名作為參數,無法指定類型啊,會報錯!那我就想啊,既然不能直接傳入,那我傳入整個對象總可以吧,通過傳進來的對象來執行該方法,如下代碼:

    using System;namespace MyEventTest{ ?

    ?public class SomeClass{ ? ? ?
    ??public void Start(int a)

    { Console.WriteLine("Go:{0}",a); }} ?
    ??
    ?? ?public class Publisher{ ? ? ?
    ?? ? ? ? ?public void StartEvent(int a, SomeClass sc) ? ? ? ?{ ? ? ? ? ? ?if (sc != null){sc.Start(a); ?//觸發回調方法}}} ?
    ???
    ????public class MainClass{ ? ? ? ?static void Main() ? ? ? ?{SomeClass some = new SomeClass();Publisher p = new Publisher();p.StartEvent(5,some); //Go:5}} }

    以上方法確實可以,但C#不完全是這樣實現事件的,因為方法的特殊性,C#引入了委托的概念,讓委托對象來代表方法作為其它方法的參數;而事件對象,其實就是一個委托對象。下面先介紹一下委托:

    委托

    對應于以上方法:
    public void Start(int a) { Console.WriteLine("Go:{0}",a); }
    我們可以定義一個委托類型:
    public delegate void MyDel(int a);

    委托的定義:

  • 委托MyDel它是一個類型,類型名就是MyDel;定義委托相當于定義一個新類,委托在后臺實現為派生自System.Delegate類。

  • 定義委托,就是告訴編譯器該委托將表示哪種方法(返回值類型+方法簽名),該方法可以是任意類型的實例方法、靜態方法,只要方法的簽名、返回值類型與委托匹配,那么該委托的實例就可以引用這些方法。

  • 使用委托,必須創建該委托的實例,并為它指定要引用的方法,如:MyDel d = some.Start;注意這里不是some.Start();

  • 委托對象支持"+","+="來為它添加更多的方法引用,而"-","-="則是刪除引用;

  • 引用了多個方法的委托就叫多播委托,多播委托派生自基類System.MulticastDelegate類,它是System.Delegate類的子類

  • 注意:只要委托對象還存在對方法的引用,它就一直占用內存哦!我想可以用d = null;來釋放委托對象d;

  • 可以對委托對象執行調用,如:d(5);它將把調用傳遞給它所引用的方法some.Start(5);,對于多播委托,它將按順序調用它引用的所有方法,但如果其中一個方法拋出異常,且沒在方法內部處理,則將會將異常往外拋出,之后的方法調用將終止。

    使用委托的規則:

  • 委托是和類一個級別的,可以在能定義類的任何地方定義委托;

  • 委托不支持繼承;

  • 可以為委托類型定義任意常見的訪問修飾符;

  • 委托對象所引用的方法也可以是匿名方法、Lambda 表達式;

  • 多播委托的返回值類型必須是void,否則就只能得到委托調用的最后一個方法的結果。

  • 在.NET 4.0中,委托開始支持協變與逆變,這樣一來,定義委托類型時的簽名可以和所要引用的方法的簽名不完全匹配(不同類型之間必須是派生關系)

  • 委托支持泛型,.NET預定義了兩個泛型版本的委托:

    • Action< T >委托表示引用一個返回值類型為void的方法,根據參數個數存在不同的變體版本;如:Action<in T1, in T2>

    • Func< T >委托表示引用一個帶返回值類型的方法,根據參數個數存在不同的變體版本;如:Func<in T1, out TResult>1個參數T1和返回值類型TResult。

  • 事件

    說完了委托的概念,就可以繼續講事件了,因為事件是基于委托的!

    事件的概念:

    • 類或對象可以通過事件向其他類或對象通知發生的相關事情。

    • 發送事件的類稱為“發行者”,接收事件的類稱為“訂閱者”。(就是設計模式中的訂閱發布者模式);

    • 一個事件可以有多個訂閱者。 一個訂閱者可處理來自多個發行者的多個事件。如果一個事件有多個訂閱者,當引發該事件時,會同步調用多個事件處理程序。也可異步調用。

    .NET Framework 類庫中的所有事件均基于?EventHandler?委托,還有泛型版本EventHandler<EventArgs>,這個委托是.NET預定義的,不需要我們定義,可以直接用它來實例化一個事件對象,定義如下:

    參數object sender對象是對發布者的實例的引用,EventArgs e對象主要用來存儲事件數據

    public delegate void EventHandler(object sender, EventArgs e); //EventArgs主要用來存儲事件數據

    public delegate void EventHandler<TEventArgs>(object sender, EventArgs e);

    雖然在自定義的類中的事件可基于任何有效委托類型,但是,通常建議使用.NET預定義事件委托類型讓事件基于 .NET 標準事件模式

    下面是我總結的發布基于 .NET 標準事件模式的4個步驟:

    第1步:在發布者類中實例化委托事件,并定義一個實例方法,用來調用委托事件(因為委托事件只能通過定義它的類的實例來調用)。

    定義發布者類之前可先定義一個用來存儲事件數據的類(它必須派生于EventArgs基類),如下:

    注意:在方法StartEvent()中,聲明了一個變量,來保存事件對象的副本,這樣在取得事件對象的副本后,到觸發事件時,這段時間內,這個事件副本就不會受其它線程的影響。如:在此期間,其它線程注銷了回調方法,那么MyEvent就為null了,這時再觸發事件將引發錯誤。(這就是線程安全的事件,當然還可以通過鎖機制,或者為事件對象始終引用一個空方法)

    public class MyEventArgs: EventArgs ?//定義存儲事件數據的類{ ?
    ?public int Current{get;set;} }
    ?
    ?public class Publisher{ ?
    ?public event EventHandler<MyEventArgs> MyEvent; //第1步:實例化委托事件public int Sum{get;set;}
    ? ?public void StartEvent(int a) ? ? ?{ ? ? ?
    ? ? ? ?var EventCopy = MyEvent; //每次都取一個副本MyEventArgs args = new MyEventArgs();args.Current = a; ? ?
    ? ? ? ?? ? ?this.Sum += a; ? ? ? ? ?if (EventCopy != null){EventCopy(this,args); ?//調用事件}} }

    第2步:定義訂閱者類,在該類中定義和委托事件相匹配的方法(事件觸發時,實際要執行的方法)

    public class Subscriber{ ? ?

    public
    void Dosomething1(object obj, MyEventArgs e) ? ?
    {Publisher p = (Publisher)obj;Console.WriteLine("Meg: Sum = {0}, Current = {1}", p.sum, e.Current);} ? ? public void Dosomething2(object obj, MyEventArgs e) ? ? {} }

    第3步:在客戶端代碼中,在發布者類的實例上為委托事件注冊回調方法

    public class MainClass {static void Main(){Publisher p = new Publisher{ Sum = 0 };Subscriber sub = new Subscriber();p.MyEvent += sub. Dosomething1; ?//注冊回調方法p.MyEvent += sub. Dosomething2;p. StartEvent( 5 ); //調用方法,間接觸發事件p.MyEvent -= sub. Dosomething1; ?//取消注冊} }

    要點:事件對象其實就是一個委托對象,把事件當委托來看,就比較容易理解了!不要被Event這個單詞給蒙蔽了!

    介紹完了!下回將介紹C#中的其它一些較難理解的概念!

    原文地址:http://www.cnblogs.com/susufufu/p/6160764.html


    .NET社區新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注

    總結

    以上是生活随笔為你收集整理的深刻理解:C#中的委托、事件的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。