国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

網(wǎng)站開發(fā)怎么樣?怎么找平臺(tái)推廣自己的產(chǎn)品

網(wǎng)站開發(fā)怎么樣?,怎么找平臺(tái)推廣自己的產(chǎn)品,電商網(wǎng)站怎么做推廣,做自媒體的網(wǎng)站目錄 本文較長,給大家提供了目錄,可以直接看自己感興趣的部分。 前言有關(guān)事件的概念示例? 簡單示例? 標(biāo)準(zhǔn) .NET 事件模式? 使用泛型版本的標(biāo)準(zhǔn) .NET 事件模式? 補(bǔ)充總結(jié) 參考前言 前面介紹了C#中的委托,事件的很多部分都與委托…

目錄

本文較長,給大家提供了目錄,可以直接看自己感興趣的部分。

前言有關(guān)事件的概念示例?   簡單示例?   標(biāo)準(zhǔn) .NET 事件模式?   使用泛型版本的標(biāo)準(zhǔn) .NET 事件模式?   補(bǔ)充總結(jié)
參考

前言

前面介紹了C#中的委托,事件的很多部分都與委托類似。實(shí)際上,事件就像是專門用于某種特殊用途的簡單委托,事件包含了一個(gè)私有的委托,如下圖所示:

image-20240102160538415

有關(guān)事件的私有委托需要了解的重要事項(xiàng)如下:

1、事件提供了對(duì)它的私有控制委托的結(jié)構(gòu)化訪問。我們無法直接訪問該委托。

2、事件中可用的操作比委托要少,對(duì)于事件我們只可以添加、刪除或調(diào)用事件處理程序。

3、事件被觸發(fā)時(shí),它調(diào)用委托來依次調(diào)用調(diào)用列表中的方法。

有關(guān)事件的概念

發(fā)布者(Publisher):發(fā)布某個(gè)事件的類或結(jié)構(gòu),其他類可以在該事件發(fā)生時(shí)得到通知。

訂閱者(Subscriber):注冊(cè)并在事件發(fā)生時(shí)得到通知的類或結(jié)構(gòu)。

事件處理程序(event handler):由訂閱者注冊(cè)到事件的方法,在發(fā)布者觸發(fā)事件時(shí)執(zhí)行。

觸發(fā)(raise)事件:調(diào)用(invoke)或觸發(fā)(fire)事件的術(shù)語。當(dāng)事件觸發(fā)時(shí),所有注冊(cè)到它的方法都會(huì)被依次調(diào)用。

示例

簡單示例

現(xiàn)在我們先來看一下最最原始的事件示例。其結(jié)構(gòu)如下所示:

image-20240103101447689

委托類型聲明:事件和事件處理程序必須有共同的簽名和返回類型,它們通過委托類型進(jìn)行描述。

事件處理程序聲明:訂閱者類中會(huì)在事件觸發(fā)時(shí)執(zhí)行的方法聲明。它們不一定有顯示命名的方法,還可以是匿名方法或Lambda表達(dá)式。

事件聲明:發(fā)布者類必須聲明一個(gè)訂閱者類可以注冊(cè)的事件成員。當(dāng)聲明的事件為public時(shí),稱為發(fā)布了事件。

事件注冊(cè):訂閱者必須訂閱事件才能在它被觸發(fā)時(shí)得到通知。

觸發(fā)事件的代碼:發(fā)布者類中”觸發(fā)“事件并導(dǎo)致調(diào)用注冊(cè)的所有事件處理程序的代碼。

現(xiàn)在我們可以照著這個(gè)思路去寫示例代碼。

首先聲明一個(gè)自定義的委托類型:

 public delegate void MyDelegate();

該委托類型沒有參數(shù)也沒有返回值。

然后再寫一個(gè)發(fā)布者類:

   public class Publisher{public event MyDelegate MyEvent;public void DoCount(){for(int i = 0; i < 10; i++) { Task.Delay(3000).Wait();            //確認(rèn)有方法可以執(zhí)行if(MyEvent != null){//觸發(fā)事件MyEvent();}}}}

事件聲明:

 public event MyDelegate MyEvent;

事件聲明在一個(gè)類中,它需要委托類型的名稱,任何注冊(cè)到事件的處理程序都必須與委托類型的簽名和返回類型匹配。它聲明為public,這樣其他類和結(jié)構(gòu)可以在它上面注冊(cè)事件處理程序。不能使用對(duì)象創(chuàng)建表達(dá)式(new表達(dá)式)來創(chuàng)建它的對(duì)象。

一個(gè)常見的誤解就是把事件認(rèn)為是類型,事件其實(shí)不是類型,它和方法、屬性一樣是類或結(jié)構(gòu)的成員。

由于事件是成員,所以我們不能在一段可執(zhí)行的代碼中聲明事件,它必須聲明在類或結(jié)構(gòu)中,和其他成員一樣。

事件成員被隱式自動(dòng)初始化為null。

事件聲明的圖解如下所示:

image-20240103140544886

觸發(fā)事件:

              //確認(rèn)有方法可以執(zhí)行if(MyEvent != null){//觸發(fā)事件MyEvent();}

也可以這樣寫:

              //確認(rèn)有方法可以執(zhí)行if(MyEvent != null){//觸發(fā)事件MyEvent().Invoke();}

這兩者是等效的,MyEvent();直接調(diào)用事件的委托,MyEvent().Invoke()使用顯式調(diào)用委托的 Invoke 方法。

現(xiàn)在再看看訂閱者類:

  public class Subscriber{          public void EventHandler(){Console.WriteLine($"{DateTime.Now}執(zhí)行了事件處理程序");}}

訂閱者類中有一個(gè)EventHandler方法,與前面定義的委托類型的簽名與返回值類型一致。

在看下主函數(shù):

 static void Main(string[] args){Publisher publisher = new Publisher();Subscriber subscriber = new Subscriber();//訂閱事件publisher.MyEvent += subscriber.EventHandler;publisher.DoCount();}
 publisher.MyEvent += subscriber.EventHandler;

就是在訂閱事件,對(duì)應(yīng)上面結(jié)構(gòu)圖中的事件注冊(cè),將subscriber類的EventHandler方法注冊(cè)到publisher類的MyEvent事件上。

也可以通過:

 publisher.MyEvent -= subscriber.EventHandler;

取消訂閱事件。

運(yùn)行結(jié)果如下所示:

image-20240103151109073

本示例全部代碼如下所示:

 internal class Program{public delegate void MyDelegate();public class Publisher{public event MyDelegate MyEvent;public void DoCount(){for(int i = 0; i < 3; i++) { Task.Delay(3000).Wait();//確認(rèn)有方法可以執(zhí)行if(MyEvent != null){//觸發(fā)事件MyEvent();}}}}public class Subscriber{          public void EventHandler(){Console.WriteLine($"{DateTime.Now}執(zhí)行了事件處理程序");}}static void Main(string[] args){Publisher publisher = new Publisher();Subscriber subscriber = new Subscriber();//訂閱事件publisher.MyEvent += subscriber.EventHandler;publisher.DoCount();}}

以上就根據(jù)上面的結(jié)構(gòu)圖寫出了一個(gè)使用事件的示例,但是本示例還有需要改進(jìn)的地方。

上面我們觸發(fā)事件檢查空值是這樣寫的:

                 //確認(rèn)有方法可以執(zhí)行if(MyEvent != null){//觸發(fā)事件MyEvent();}

C# 6.0 引入了空條件操作符之后,現(xiàn)在也可以這樣做空值檢查:

 MyEvent?.Invoke();

同時(shí)也不是一上來就檢查空值,而是先將MyEvent賦給第二個(gè)委托變量localDelegate:

 MyDelegate localDelegate = MyEvent;localDelegate?.Invoke();

這個(gè)簡單的修改可確保在檢查空值和發(fā)送通知之間,如果一個(gè)不同的線程移除了所有MyEvent訂閱者,將不會(huì)引發(fā)NullReferenceException異常。

標(biāo)準(zhǔn) .NET 事件模式

以上我們以一個(gè)簡單的例子介紹了C#中的事件,但是大家可能會(huì)覺得有點(diǎn)模式,跟我們平常在winform中使用的事件好像不太一樣,那是因?yàn)?.NET 框架提供了一個(gè)標(biāo)準(zhǔn)模式,接下來我將以winform中的button按鈕點(diǎn)擊事件為例進(jìn)行介紹。

頁面很簡單,只有一個(gè)button按鈕:

image-20240104093125527

然后button按鈕點(diǎn)擊事件的代碼如下:

 private void button1_Click(object sender, EventArgs e){MessageBox.Show("Hello World");}

現(xiàn)在我們?cè)俑鶕?jù)下面這張事件結(jié)構(gòu)圖,來看一看標(biāo)準(zhǔn)的 .NET 事件模式:

image-20240103101447689

事件注冊(cè)

打開解決方案中的Form1.Designer.cs文件:

image-20240104093502598

看到button1相關(guān)內(nèi)容:

image-20240104093620010

button1.Click += button1_Click;

就是在訂閱事件,對(duì)應(yīng)上面圖中的事件注冊(cè)。

委托類型聲明

右鍵查看定義:

 public event EventHandler? Click{add => Events.AddHandler(s_clickEvent, value);remove => Events.RemoveHandler(s_clickEvent, value);}

發(fā)現(xiàn)Click事件中的委托類型是EventHandler,再查看EventHandler的定義:

 public delegate void EventHandler(object? sender, EventArgs e);

這一步對(duì)應(yīng)上面事件結(jié)構(gòu)圖中的委托類型聲明。

EventHandler是 .NET中預(yù)定義的委托,專門用來表示不生成數(shù)據(jù)的事件的事件處理程序方法應(yīng)有的簽名與返回類型。

第一個(gè)參數(shù)是sender,用來保存觸發(fā)事件的對(duì)象的引用。由于是object?類型,所以可以匹配任何類型的實(shí)例。

第二個(gè)參數(shù)是e,用于傳遞數(shù)據(jù)。但是EventArgs類表示包含事件數(shù)據(jù)的類的基類,并提供用于不包含事件數(shù)據(jù)的事件的值。也就是說EventArgs設(shè)計(jì)為不能傳遞任何數(shù)據(jù)。它用于不需要傳遞數(shù)據(jù)的事件處理程序,通常會(huì)被忽略。如果我們想要傳遞數(shù)據(jù),必須聲明一個(gè)派生自EventArgs的類,使用合適的字段來保存需要傳遞的數(shù)據(jù)。

盡管EventArgs類實(shí)際上并不傳遞數(shù)據(jù),但它是使用EventHandler委托模式的重要部分。不管參數(shù)使用的實(shí)際類型是什么,object類和EventArgs類總是基類,這樣EventHandler就能提供一個(gè)對(duì)所有事件和事件處理器都通用的簽名,只允許兩個(gè)參數(shù),而不是各自都有不同簽名。

事件聲明
 public event EventHandler? Click{add => Events.AddHandler(s_clickEvent, value);remove => Events.RemoveHandler(s_clickEvent, value);}

Click事件在Control類中定義,Button類繼承自ButtonBase類,而ButtonBase類繼承自Control類。

public event EventHandler? Click;

對(duì)應(yīng)上面結(jié)構(gòu)圖中的事件聲明。

觸發(fā)事件的代碼

查看Button類的定義,找到OnClick方法的定義:

 protected override void OnClick(EventArgs e){Form? form = FindForm();if (form is not null){form.DialogResult = _dialogResult;}// accessibility stuffAccessibilityNotifyClients(AccessibleEvents.StateChange, -1);AccessibilityNotifyClients(AccessibleEvents.NameChange, -1);// UIA events:if (IsAccessibilityObjectCreated){AccessibilityObject.RaiseAutomationPropertyChangedEvent(UiaCore.UIA.NamePropertyId, Name, Name);AccessibilityObject.RaiseAutomationEvent(UiaCore.UIA.AutomationPropertyChangedEventId);}base.OnClick(e);}

去掉無關(guān)部分,保留相關(guān)部分便于理解:

 protected override void OnClick(EventArgs e){base.OnClick(e);
}    

這里的base指的是Button類的基類ButtonBase類:

image-20240104103143021

再查看ButtonBase類中OnClick方法的定義:

 protected override void OnClick(EventArgs e){base.OnClick(e);OnRequestCommandExecute(e);}

發(fā)現(xiàn)也有一個(gè)base.OnClick(e);,這里的base指的是ButtonBase類的基類Control

image-20240104103450257

再查看Control類中OnClick方法的定義:

 /// <summary>///  Raises the <see cref="Click"/>///  event./// </summary>[EditorBrowsable(EditorBrowsableState.Advanced)]protected virtual void OnClick(EventArgs e){((EventHandler?)Events[s_clickEvent])?.Invoke(this, e);}

終于找到了觸發(fā)事件的代碼。

事件處理程序

這個(gè)想必大家并不陌生,雙擊button按鈕就可以看到:

  private void button1_Click(object sender, EventArgs e){MessageBox.Show("Hello World");}

這對(duì)應(yīng)上面結(jié)構(gòu)圖中的事件處理程序。該事件處理程序方法的簽名與返回值類型與EventHandler委托類型一致。

使用泛型版本的標(biāo)準(zhǔn) .NET事件模式

接下來我會(huì)舉一個(gè)例子,說明如何使用泛型版本的標(biāo)準(zhǔn) .NET事件模式。

第一步,自定義事件數(shù)據(jù)類,該類繼承自EventArgs類:

  public class MyEventArgs : EventArgs{public string? Message {  get; set; }public DateTime? Date {  get; set; }}

擁有兩個(gè)屬性Message與Date。

第二步,寫發(fā)布者類:

  public class Publisher{public event EventHandler<MyEventArgs>? SendMessageEvent;public void SendMessage(){for(int i = 0; i < 3; i++){Task.Delay(3000).Wait();MyEventArgs e = new MyEventArgs();e.Message = $"第{i+1}次觸發(fā)事件";e.Date = DateTime.Now;EventHandler<MyEventArgs>? localEventHandler = SendMessageEvent;localEventHandler?.Invoke(this, e);}}}
public event EventHandler<MyEventArgs>? SendMessageEvent;

聲明了事件。

 EventHandler<MyEventArgs>? localEventHandler = SendMessageEvent;localEventHandler?.Invoke(this, e);

觸發(fā)了事件。

第三步,寫訂閱者類:

 public class Subscriber{public void EventHandler(object? sender,MyEventArgs e){Console.WriteLine($"Received Message:{e.Message} at {e.Date}");}}

包含事件處理程序,該方法與EventHandler<MyEventArgs>委托類型的簽名與返回值類型一致。

第四步,寫主函數(shù):

  static void Main(string[] args){Publisher publisher = new Publisher();Subscriber subscriber = new Subscriber();publisher.SendMessageEvent += subscriber.EventHandler;publisher.SendMessage();}
 publisher.SendMessageEvent += subscriber.EventHandler;

訂閱事件。

運(yùn)行結(jié)果如下所示:

image-20240104115222746

包含了我們自定義的事件數(shù)據(jù)。

補(bǔ)充

上面說自定義的事件數(shù)據(jù)類要繼承自EventArgs類,但其實(shí)在 .NET Core 的模式較為寬松。 在此版本中,EventHandler<TEventArgs> 定義不再要求 TEventArgs 必須是派生自 System.EventArgs 的類。

因此我在.NET 8 版本的示例中去掉繼承自EventArgs類,該示例依舊能正常運(yùn)行。

異步事件訂閱者

一個(gè)關(guān)于異步事件訂閱者的例子如下:

// 事件發(fā)布者
public class EventPublisher
{// 定義異步事件public event Func<string, Task>? MyEvent;// 觸發(fā)事件的方法public async Task RaiseEventAsync(string message){Func<string, Task> localEvent = MyEvent;await localEvent?.Invoke(message);}
}// 異步事件訂閱者
public class AsyncEventSubscriber
{// 處理事件的異步方法public async Task HandleEventAsync(string message){Console.WriteLine($"Received event with message: {message}");// 異步操作,例如IO操作、網(wǎng)絡(luò)請(qǐng)求等await Task.Delay(3000);Console.WriteLine("Event handling complete.");}
}class Program
{static async Task Main(string[] args){// 創(chuàng)建事件發(fā)布者var publisher = new EventPublisher();// 創(chuàng)建異步事件訂閱者var subscriber = new AsyncEventSubscriber();// 訂閱事件publisher.MyEvent += subscriber.HandleEventAsync;// 觸發(fā)事件await publisher.RaiseEventAsync("Hello, world!");Console.ReadLine();}
}

運(yùn)行結(jié)果如下所示:

image-20240104123351663

總結(jié)

本文先是介紹了一些C#中事件的相關(guān)概念,然后通過幾個(gè)例子介紹了在C#中如何使用事件。

參考

1、《C#圖解教程》

2、《C# 7.0 本質(zhì)論》

3、[C# 文檔 - 入門、教程、參考。 | Microsoft Learn](

http://www.aloenet.com.cn/news/31955.html

相關(guān)文章:

  • 網(wǎng)頁qq家園seo排名賺錢
  • 怎么自己做視頻網(wǎng)站免費(fèi)找客戶軟件
  • 學(xué)做吃的網(wǎng)站國外最好的免費(fèi)建站
  • 電子商務(wù)網(wǎng)站建設(shè)與管理第四章答案推廣網(wǎng)站的公司
  • 蘋果手機(jī)做網(wǎng)站服務(wù)器深圳網(wǎng)站制作設(shè)計(jì)
  • 網(wǎng)站建設(shè)套餐方案通過qq群可以進(jìn)行友情鏈接交換
  • 長沙廣告公司排行榜上海優(yōu)化網(wǎng)站
  • 工程在哪個(gè)網(wǎng)站做推廣比較合適長沙正規(guī)競價(jià)優(yōu)化推薦
  • 做彩鈴的網(wǎng)站近期國家新聞
  • 重慶南川網(wǎng)站制作公司哪家專業(yè)sem搜索引擎營銷
  • 網(wǎng)站推廣的8種方法東莞網(wǎng)絡(luò)推廣代運(yùn)營
  • 站外調(diào)用WordPress評(píng)論網(wǎng)絡(luò)營銷策略案例分析
  • 網(wǎng)站建設(shè)技術(shù)支持牛商網(wǎng)kol營銷
  • 青島網(wǎng)站設(shè)計(jì)微動(dòng)力百家號(hào)推廣團(tuán)隊(duì)
  • 蘋果手機(jī)允許網(wǎng)站設(shè)置百度廣告聯(lián)盟app下載官網(wǎng)
  • 有什么軟件做短視頻網(wǎng)站免費(fèi)網(wǎng)站生成器
  • 掃描二維碼進(jìn)入公司網(wǎng)站怎樣做原創(chuàng)文章代寫平臺(tái)
  • 申請(qǐng)微官網(wǎng)的網(wǎng)站百度關(guān)鍵詞首頁排名怎么上
  • asp做網(wǎng)站搜索免費(fèi)seo教程分享
  • phpcmsv9手機(jī)網(wǎng)站模板建設(shè)網(wǎng)站的步驟
  • 西安建委官網(wǎng)太原seo網(wǎng)站優(yōu)化
  • 龍溪營銷型網(wǎng)站制作好123上網(wǎng)主頁
  • 微網(wǎng)站怎么做的好網(wǎng)站優(yōu)化推廣公司
  • 做海報(bào)可以在哪些網(wǎng)站下載素材萊陽seo外包
  • 廣東品牌網(wǎng)站設(shè)計(jì)專家百度云網(wǎng)盤網(wǎng)頁版
  • 設(shè)計(jì)大神云集的網(wǎng)站是網(wǎng)絡(luò)推廣方法怎么樣
  • 怎樣增加網(wǎng)站收錄量谷歌瀏覽器引擎入口
  • 展示類網(wǎng)站建設(shè)qianhu微建站
  • 點(diǎn)網(wǎng)站出圖片怎么做網(wǎng)站開發(fā)培訓(xùn)
  • 沈陽網(wǎng)站建設(shè)培訓(xùn)學(xué)校怎么建網(wǎng)站教程圖解