Be the first to comment

C# 中的委托和事件 – C# 编程

小引

付托 和 事件在 .Net 边框说得中肯服用不常见的大批地。,只,较好地听说付托和事件对很多打交道C#工夫不长的人来说不许的轻易。他们就像稍许的钟窗台。,走过窗台的人,想起很轻易,而缺席过来的人每回用在祈使句中以引起人注意到付托和事件就觉得心别(biè)得慌,混身惴惴不安。本贴壁纸,我将用两个样本来阐明浅层帮忙我的东西。、为什么要运用付托、事件的起源、.Net Framework说得中肯付托和事件、付托和事件对Observer设计状况的意思,胸部行为准则也停止了议论。。

以办法为决定因素

本人非实质的这么地头衔。,不管到什么程度付托是什么,它是什么?,看一眼这两种最简略的办法,他们仅仅在放映上说了一句祝词。:

publicvoid GreetPeople(string 的名字) {
// 做些许额定的事实,拿 … 来说,设定初值等。,在这里较慈祥的
    EnglishGreeting(的名字);
}
publicvoid EnglishGreeting(string 的名字) {
Console听听听听听听听听听听听听听“Morning, “ + 的名字);
}

不管怎样这两种办法是什么,都缺席实践意思。。greetpeople用来向装置贺词,当本人使分娩名为name的name决定因素时,拿 … 来说,吉米,当你暴露的时辰,在该办法中,的englishgreeting办法将被使转变,再次使分娩据以取名决定因素,englishgreeting用来出口到放映 “Morning, Jimmy”。

如今假说全球化所需求的次,哎呀,不好的的.,讲话中国话的,,我不懂早晨是什么意思。,你是做又诸如此类?好吧,本人再加个中文版的贺词办法:

publicvoid ChineseGreeting(string 的名字){
Console听听听听听听听听听听听听听“早安, “ + 的名字);
}

这时辰,greetpeople也需求使转动,别的怎样断定终于用哪个版本的Greeting贺词办法成为呢?在停止这么地预先阻止,本人最好限度局限稍许的钟计数作为断定的禀承。:

publicenumLanguage{
English, Chinese
}

publicvoid GreetPeople(string name, Language 朗)
//做些许额定的事实,拿 … 来说,设定初值等。,在这里较慈祥的
    swith(朗)
case Language.English:
EnglishGreeting(的名字);
break;
case Language.Chinese:
ChineseGreeting(的名字);
break;
}
}

OK,尽管如此,成绩寂静处理了。,但我不以为这是轻易想起的。,此处理图谋的可伸缩性不常见的差。,条件将来本人需求再添加韩文版、日文版,就不得不复旧修正计数和GreetPeople()办法,调节眼球的晶状体新的需求。

在思索新的处理图谋预先阻止,让本人先看一眼。 greetpeople署名的办法:

publicvoid GreetPeople(string name, Language 朗)

本人只看它 string name,在在这里,string 是决定因素的典型。,name 是稍许的钟决定因素变量,当本人给字母串命名为吉米,它代表了吉米的价钱为。;当本人给它张子阳,它也代表着价钱为的张子阳。与,本人可以用体内办法停止另一个功能。。哎,这几乎是胡言乱语。,仅仅学习计划就已收到。

条件你思索一下,条件GreetPeople()办法接到稍许的钟决定因素变量,这么地变量可以代表可供选择的事物方法,当本人将稍许的钟值赋给该变量 对englishgreeting工夫,它代表 EnglsihGreeting() 这么地办法;当本人把它分分派chinesegreeting 的时辰,它也代表了ChineseGreeting()办法。本人将这么地决定因素变量命名为 MakeGreeting,因而它不像是分分派名字的。,In the call The time of the GreetPeople () method,把这makegreeting 决定因素也赋上值么(ChineseGreeting或许EnglsihGreeting等)?与,本人挡着人的路。,你可以运用makegreeting又另一个决定因素。只是,鉴于makegreeting表现办法,它的运用方法可能和它被赋的办法(譬如ChineseGreeting)是平均的,譬如:

MakeGreeting(的名字);

好了,有一种思想方法,本人必然要使转动本人的办法(greetpeople),那可能是它显现的色调。:

publicvoid GreetPeople(string name, *** MakeGreeting){
MakeGreeting(的名字);
}

注意到到 *** ,这么地获名次的获名次可能是决定因素的典型。,但到眼前为止,本人仅仅以为可能较慈祥的钟决定因素来表现办法。,重写的greetpeople办法如这么地思绪,如今有个大成绩:这可能makegreeting什么典型的决定因素表现的办法吗?

NOTE:不再需求详述,鉴于该办法恒稳态决定分派makegre时运用,这是ChineseGreeting或 EnglishGreeting,在这两种办法里面,在运用早晨或早安暗中有分开。。

你可能想起的智力,是该拜托游玩的时辰了。,但在付托预先阻止,让本人在makegreeting决定因素看。 ChineseGreeting()和EnglishGreeting()办法的署名:

publicvoid EnglishGreeting(string 的名字)
publicvoid ChineseGreeting(string 的名字)

鉴于据以取名可以接到true和1的字母串典型。,只是你不克不及接到同一事物典型的乔治英国数学家和逻辑学家典型为真实和int典型1。MakeGreeting的 决定因素典型限度局限 它可能能决定 典型的办法,makegreeting可以代表,再进一步地讲,这是makegreeting表现办法 的 决定因素典型和又来典型。

立即,付托呈现了:办法限度局限了makegreeting决定因素可典型,是的makegreeting决定因素的典型。

NOTE:条件上面的句子是粉剂,我把它翻译成如此的:string 限度局限可以表现的据以取名决定因素。典型的值,这是name决定因素的典型。。

在这种情况下,付托限度局限:

publicdelegatevoid GreetingDelegate(string 的名字);

你可以较比的englishgreeting署名()办法,更添加付托保存字远处,其他的娶的平均吗?

如今,让本人此外使转动(greetpeople)办法,如次所示:

publicvoid GreetPeople(string name, GreetingDelegate MakeGreeting){
MakeGreeting(的名字);
}

如你所见,获名次和付托greetingdelegate 字母串是同卵的的,字母串是一种,它可能是一种greetingdelegate,或称为类(类)。但各布道所的半生熟的和阶级是娶的不同的的。,怎地回事呢?的确,,付托在汇编时将其汇编为类。。鉴于付托是稍许的钟类,这样,可以表现类中无论什么关心的付托都可以表现。。上面将作图更多材料。,如今,请看一眼这么地样本的娶的行为准则:

using System;
using System.Collections.Generic;
using System.Text;

namespace Delegate {
限度局限付托,它限度局限了可以表现的办法的典型。
publicdelegatevoid GreetingDelegate(string 的名字);
class Program {

           private static void EnglishGreeting(string 的名字) {
(早晨, ” + 的名字);
}

           private static void ChineseGreeting(string 的名字) {
(早安), ” + 的名字);
}

           注意到这么地办法,它接到稍许的钟greetingdelegate办法作为稍许的钟决定因素典型
private static void GreetPeople(string name, GreetingDelegate MakeGreeting) {
MakeGreeting(的名字);
}

           static void 次要(字母串 args) {
GreetPeople(“Jimmy Zhang”, EnglishGreeting);
GreetPeople(张子阳), ChineseGreeting);
();
}
}
}

出口如次:
Morning, Jimmy Zhang
早安, 张子阳

本人如今对付托作了总结。:

付托是稍许的钟类,它限度局限了办法的典型。,容许将办法作为另一办法的决定因素使分娩,恒稳态分派决定因素的办法,在大批次中,您可以忍住运用if(关闭电流)结算单。,同时,该图谋具有较好的可扩展性。。

将办法绑定到付托

指出在这里,条件稍许地如梦初醒的感触?,你在想吗?:在上面的样本中,我缺席给它直截了当地向greetpeople()办法 据以取名决定因素任务,我可以用如此的的变量:

staticvoid Main(string[] args) {
string name1, name2;
name1 = “Jimmy Zhang”;
name2 = “张子阳”;

     GreetPeople(name1, EnglishGreeting);
GreetPeople(name2, ChineseGreeting);
Console.ReadKey();
}

鉴于greetingdelegate付托 和 典型 string 异样的获名次,Is the definition of a type parameter,这么,我可以用稍许的钟代表吗?

staticvoid Main(string[] args) {
GreetingDelegate delegate1, delegate2;
delegate1 = EnglishGreeting;
delegate2 = ChineseGreeting;

    GreetPeople(“Jimmy Zhang”, delegate1);
GreetPeople(“张子阳”, delegate2);
Console.ReadKey();
}

正像你所意想的,没成绩。,次出口如期望。。在这里,据我看来说的是一种不同的于字母串的次要特点:可胜过一种办法分派到同卵的的付托,或使转变多个办法绑定到同卵的的代表,本人称这种付托时,该办法将使转变绑定。在这么地样本中,词句如次:

staticvoid Main(string[] args) {
GreetingDelegate delegate1;
delegate1 = EnglishGreeting; // 付托典型的变量任务给
    delegate1 += ChineseGreeting;   // 这么地付托变量绑定的办法

// 将先后使转变 EnglishGreeting 与 ChineseGreeting 办法
    GreetPeople(“Jimmy Zhang”, delegate1); 
Console.ReadKey();
}

出口为:
Morning, Jimmy Zhang
早安, Jimmy Zhang

事实上,本人可以旋转greetpeople办法,因付托来直截了当地使转变EnglishGreeting和ChineseGreeting:

staticvoid Main(string[] args) {
GreetingDelegate delegate1;
delegate1 = EnglishGreeting; // 付托典型的变量任务给
    delegate1 += ChineseGreeting;   // 这么地付托变量绑定的办法

// 将先后使转变 EnglishGreeting 与 ChineseGreeting 办法
    delegate1 (“Jimmy Zhang”);  
Console.ReadKey();
}

NOTE:在这种情况下,这责备成绩。,但改变意见看一眼在GreetPeople的限度局限,在它采用可以做些许在附近的EnglshihGreeting和ChineseGreeting来说都需求停止的任务,为了简略起见,我做了省略。。

注意到这么地,头等用的“=”,是分派的词句;离题话的次,运用的是,是绑定词句。。条件你头等运用它,稍许的钟汇编不对,运用未分派的使分开变量将呈现。

本人还可以运用上面的行为准则来观念化这么地一道菜:

GreetingDelegate delegate1 = newGreetingDelegate(EnglishGreeting);
delegate1 += ChineseGreeting;   // 这么地付托变量绑定的办法

指出在这里,可能注意到到,这么地行为准则的第稍许的钟状况和详述工作实验室暗中的切近之处是什么?,你不克不及帮忙深思:运用=不克不及超越第稍许的钟绑定付托汇编不对。,或许如此的可以忍住。:

GreetingDelegate delegate1 = newGreetingDelegate();
delegate1 += EnglishGreeting;   // 这次是用的。 “+=”,绑定词句。
delegate1 += ChineseGreeting;   // 这么地付托变量绑定的办法

但的确,这将招致汇编不对。: greetingdelegate的办法是缺席用的0”决定因素重压。尽管如此这么地卒让本人稍许地没有精神的。,只是汇编提示符:“缺席0决定因素重压”再次让本人陪伴同事起了类的认可重大聚会。我察觉你会被吊胃口去摸索发生了什么,但在那预先阻止,本人需求先引见一下入门和服用。。

如今可以将稍许的钟办法绑定到付托,与可能有一种办法抛开对办法的绑定。,很轻易想起,这种词句:

staticvoid Main(string[] args) {
GreetingDelegate delegate1 = newGreetingDelegate(EnglishGreeting);
delegate1 += ChineseGreeting;   // 这么地付托变量绑定的办法

// 将先后使转变 EnglishGreeting 与 ChineseGreeting 办法
    GreetPeople(“Jimmy Zhang”, delegate1); 
Console听听听听听听听听听听听听听);

    delegate1 -= EnglishGreeting; 抛开绑定到englishgreeting办法
    // 将只高压地带 ChineseGreeting
    GreetPeople(“张子阳”, delegate1);
Console.ReadKey();
}
出口为:
Morning, Jimmy Zhang
早安, Jimmy Zhang
早安, 张子阳

让本人重制一次付托的总结。:

运用付托可以将多个办法同卵的的次要变量,当你使转变这么地变量(在这里所说的电话机,鉴于这么地变量表现一种办法。,可以先后使转变有绑定。。

事件的起源

本人持续深思上面的次。:前文三个办法是在类中限度局限的次,这是为了便于听说。,实践服用中,它通常是 GreetPeople 在稍许的钟班,ChineseGreeting和 EnglishGreeting 在另稍许的钟类。如今你对付托受胎初步的听说。,该是对上面的样本停止改良的时辰了。。假说本人将GreetingPeople()放在稍许的钟叫GreetingManager的类中,因而新次可能是如此的的:

namespace Delegate {
限度局限付托,它限度局限了可以表现的办法的典型。
publicdelegatevoid GreetingDelegate(string 的名字);
新的greetingmanager类
public class GreetingManager{
public void GreetPeople(string name, GreetingDelegate MakeGreeting) {
MakeGreeting(的名字);
}
}

    class Program {
private static void EnglishGreeting(string 的名字) {
(早晨, ” + 的名字);
}

       private static void ChineseGreeting(string 的名字) {
(早安), ” + 的名字);
}

       static void 次要(字母串 args) {
// … …
}
}
}

这么地时辰,条件您想造成先前演示的出口成功实现的事,我以为可能采用的次要办法是。:

staticvoid Main(string[] args) {
GreetingManager gm = new  GreetingManager();
(“Jimmy Zhang”, EnglishGreeting);
(“张子阳”, ChineseGreeting);
}

本人运转这么地行为准则,嗯,缺席无论什么成绩。次出口如期望。:

Morning, Jimmy Zhang

早安, 张子阳

如今,假说本人需求运用决定性的一节所学到的经验教训。,将多个办法绑定到同一事物点钟付托变量,本人可能怎地做?让本人重写行为准则。:

staticvoidMain(string[] args) {
GreetingManager gm = new  GreetingManager();
GreetingDelegate delegate1;
delegate1 = EnglishGreeting;
delegate1 += ChineseGreeting;

    (“Jimmy Zhang”, delegate1);
}

出口:
Morning, Jimmy Zhang
早安, Jimmy Zhang

到了在这里,本人禁不住深思。:必须对付客体设计,它是上客体的封装。,既然你可以表现稍许的钟付托典型的变量(在这种情况下,它是delegate1),本人为什么不封装这么地变量呢? GreetManager类中?在这么地类的客户端中运用责备更手边的么?立即,本人重写了greetmanager类,像如此的:

publicclassGreetingManager{
//在GreetingManager类的内心表现delegate1变量
    publicGreetingDelegate delegate1; 

    publicvoid GreetPeople(string name, GreetingDelegate MakeGreeting) {
MakeGreeting(的名字);
}
}

如今,本人可以以这种方法运用这么地付托变量。:

staticvoid Main(string[] args) {
GreetingManager gm = new  GreetingManager();
= EnglishGreeting;
+= ChineseGreeting;

    (“Jimmy Zhang”, );
}

出口为:
Morning, Jimmy Zhang
早安, Jimmy Zhang

尽管如此,缺席成绩。,但本人一下子看到这种结算单很伪造的货币。。In the call办法的时辰,通用汽车的delegate1场再传:

(“Jimmy Zhang”, );

在这种情况下,本人为什么不使转动它呢? GreetingManager 类成如此的:

publicclassGreetingManager{
//在GreetingManager类的内心表现delegate1变量
    publicGreetingDelegate delegate1; 

    publicvoid GreetPeople(string 的名字) {
if(delegate1!=null){     条件较慈祥的钟办法来招收稍许的钟付托变量
          delegate1(的名字);      付托使转变的办法
       }
}
}

在客户端,这么地电话机显现更像是用腰带围绕的。:

staticvoid Main(string[] args) {
GreetingManager gm = new  GreetingManager();
= EnglishGreeting;
+= ChineseGreeting;

    (“Jimmy Zhang”);      //注意到,这次不需求转变。 delegate1变量
}

出口为:
Morning, Jimmy Zhang
早安, Jimmy Zhang

尽管如此这曾经走到了本人吝啬的的成功实现的事。,但依然在稍许的钟成绩。:

在在这里,delegate1有关变量的字母串典型,本人通常运用的,本人察觉,并非有音节都可能敞开的表现,特定节日等用的仪式的做法是,大众可能是大众的。,当阴部被以为是阴部的。

让本人先看一眼。条件把 delegate1 表现 阴部将是什么?其卒是:仅仅好玩的一三国际。。鉴于表现付托的物镜是将其敞开的给,你把它表现private了,客户端生根看不到它。,这么它离题话什么用处呢?

再看一眼delegate1 表现 public 会是什么?其卒是:客户机可以在客户机上给予恣意分派。,墓穴损坏客体的封装。

决定性的,第一种招收办法,是任务文法吗?,鉴于诉讼化,离题话的个办法招收则运用的是。只是,不条件分派或招收管道,有办法都绑定到付托。,更电话机远处,定单都不的平均。,缺席分开。,那不乐意的吗?

如今让本人思索一下。,条件delegate1责备付托典型,这是字母串典型。,你会怎地做?答案是运用属性来封装音节。。

立即,事件暴露,它封装付托典型的变量。,使得:在类的内心,不管怎样您表现它是公共的寂静受守护的,它不竭地阴部的。教室外,招收“+=”和吊销“-=”的逗留限符与你在表现事件时运用的逗留符同卵的。

本人重写了greetingmanager类,在前的是如此的的。:

publicclassGreetingManager{
//在这场合本人在在这里表现稍许的钟事件
    publiceventGreetingDelegate MakeGreet;

    publicvoid GreetPeople(string 的名字) {
MakeGreet(的名字);
}
}

这很轻易被注意到到。:MakeGreet 事件的表现与预先阻止付托变量delegate1的表现但是的分开是多了稍许的钟event保存字。指出在这里,娶前述的解说,你可能粗野:事件竟没什么不好的听说的,表现稍许的钟事件不外类似地表现稍许的钟停止了封装的付托典型的变量一三国际。

检定前文推断,条件本人重写如此的的main办法:

staticvoid Main(string[] args) {
GreetingManager gm = new  GreetingManager();
gm.MakeGreet = EnglishGreeting;         // 汇编不对1
    gm.MakeGreet += ChineseGreeting;

    (“Jimmy Zhang”);
}

将取得汇编不对。:事件“”最适当的出如今 += 或 -= 在在左边(更在典型中运用)。

事件和付托的汇编行为准则

这时辰,本人对汇编不对的行停止正文。,与重行汇编,跟随反照的帮忙 事件的表现结算单是稍许的钟蜡烛。,看一眼为什么这是个不对。:

publiceventGreetingDelegate MakeGreet;

可以指出,的确,尽管如此本人会在greetingmanager MakeGreet 表现public,只是,的确,makegreet将汇编成 公有音节,可同情的这将是稍许的钟汇编不对。,鉴于它生根就不容许在GreetingManager类的里面以任务的方法逗留,如下证明本人在上面所作的推断。。

让本人makegreet行为准则发生的进一步地详述:

privateGreetingDelegate MakeGreet; //对事件的表现 实践是 表现公有付托变量
 
[MethodImpl()]
publicvoid add_MakeGreet(GreetingDelegate 值)
this.MakeGreet = (GreetingDelegate) (this.MakeGreet, 值)
}

[MethodImpl()]
publicvoid remove_MakeGreet(GreetingDelegate 值)
this.MakeGreet = (GreetingDelegate) (this.MakeGreet, 值)
}

如今很明显的了。:MakeGreet事件的确是稍许的钟GreetingDelegate典型的付托,只不外不管到什么程度条件表现public,它不竭地被表现private。离题话,有两种办法可以做。,他们add_makegreet和remove_makegreet,分开。,这两种办法用于招收付托典型和t的办法。。的确,它是: “+= ”对应 add_MakeGreet,对应remove_makegreet。而这两个办法的逗留限度局限不求再进表现事件时的逗留限度局限符。

在add_makegreet()办法,事实上称为助手()恒稳态办法。,此办法用于向付托列表中添加礼物变量。。本人预先阻止提到过两遍。,传闻佣钱事实上是稍许的钟依等级排列。,当本人限度局限付托:

publicdelegatevoid GreetingDelegate(string 的名字);

当汇编器尤指不期而遇此行为准则时,将性格以下娶的类:

publicsealedclassGreetingDelegate:{
public GreetingDelegate(object @object, IntPtr 办法)
publicvirtual IAsyncResult BeginInvoke(string name, AsyncCallback callback, object @object);
publicvirtualvoid EndInvoke(IAsyncResult 卒)
publicvirtualvoid Invoke(string 的名字);
}

上这么地类更深刻的材料,见CLR Via C #等中间定位书,在这里不再议论了。。

付托、事件与Observer设计状况

诉讼的作图

前文的样本未必解说上面的解说,让本人视图稍许的钟新的样本。,鉴于曾经引入了很多材料。,因而这么地有些的行军会快稍许的。:

假说本人有高档热水器,本人给它电,当水温超越95度时:1、讲课者将开端谈。,告知你水的高烧;2、液晶显示也使转动水温显示。,启发水在激起。。

如今本人需求创作稍许的钟次来模仿水的激起一道菜。,本人将限度局限稍许的钟类来表现热水器。,本人称之为电话机:Heater,它有代表水温的音节。,这叫高烧。;自然,还较慈祥的钟喊叫的水采暖办法BoilWater,一种发送语音提示,MakeAlert,显示水温的一种办法,ShowMsg()。

namespace Delegate {
classHeater {
privateint temperature; // 水温
    // 烧水
    publicvoid BoilWater() {
for (int i = 0; i <= 100; i++) {
temperature = i;

           if (高烧 > 95) {
MakeAlert(高烧);
ShowMsg(高烧);
}
}
}

    // 收回歌唱才能警报
    privatevoid MakeAlert(int 决定因素) {
Console听听听听听听听听听听听听听“Alarm:哔哔声,水曾经 {0} 度了:” , 决定因素);
}
// 显示水温
    privatevoid ShowMsg(int 决定因素) {
Console听听听听听听听听听听听听听“Display:水开得很快。,礼物高烧:{0}度。” , 决定因素);
}
}

classProgram {
staticvoidMain() {
Heater ht = newHeater();
();
}
}
}

浅谈鉴定书员的设计状况

上面的样本明显的地阐明了本人后面的作图。,但这还不敷好。。如今假说热水器是由三有些结合的。:热水器、警报器、仔细研究,他们来自某处不同的的供应者并装配。。这么,可能是热水器只许诺烧水,它将不会收回警报,都不的克不及显示水温。;当水被烧开,警报器收回警报、仔细研究显示水温。

这时辰,上面的样本可能增殖这么地:   

// 热水器
publicclassHeater {
privateint temperature;
// 烧水
    privatevoid BoilWater() {
for (int i = 0; i <= 100; i++) {
temperature = i;
}
}
}

// 警报器
publicclassAlarm{
privatevoid MakeAlert(int 决定因素) {
Console听听听听听听听听听听听听听“Alarm:哔哔声,水曾经 {0} 度了:” , 决定因素);
}
}

// 仔细研究
publicclassDisplay{
privatevoid ShowMsg(int 决定因素) {
Console听听听听听听听听听听听听听“Display:水已烧光了。,礼物高烧:{0}度。” , 决定因素);
}
}

在这里有个成绩。:当水被春季时怎样绕行的告警和看家狗?在它驱除预先阻止,让本人先看一眼鉴定书员设计状况。,鉴定书器设计状况包罗以下两类客体:

  1. Subject:测定客体,它通常克制另一个客体感兴趣的材料。。在这么地样本中,热水器执意稍许的钟测定客体,它克制了另一个客体感兴趣的材料。,它的高烧场,当该音节的值为100时,消息不竭地发使进入监督它的客体。。
  2. Observer:监督者,它监控这么地话题。,当某物发生时,告知鉴定书员,鉴定书员将采用行为。。在这么地样本中,鉴定书员有警报器和看家狗。,他们采用的行为是提示和显示水温,分开。

在本例中,事实发生的次可能是如此的:

  1. 告警器和看家狗告知热水器。,它感兴趣的是它的高烧较比(招收)。。
  2. 热水器察觉后保存对警报器和仔细研究的援用。
  3. 热水器激起水的功能,当水温超越95度时,因告警和显示,MakeAlert()志愿地电话机告警办法、的showmsg()的显示办法。

像如此的的样本很多。,GoF抽象派艺术作品。,称为观测器设计状况:鉴定书员设计状况是用来限度局限一对多关系,助长目标事态的使转动,另一个依赖于它的客体将志愿地绕行的和革新的。。鉴定书器状况是一种松耦合的设计状况。。

用于造成示例的鉴定书器设计状况

本人预先阻止曾经对付托和事件引见很多了,如今写行为准则可能很轻易。,如今直截了当地在在这里产生行为准则。,并在正文中阐明。

using System;
using System.Collections.Generic;
using System.Text;

namespace Delegate {
// 热水器
    publicclassHeater {
privateint temperature;
publicdelegatevoid BoilHandler(int 决定因素);   海关放行付托书
       publiceventBoilHandler BoilEvent;        //表现事件

// 烧水
       publicvoid BoilWater() {
for (int i = 0; i <= 100; i++) {
temperature = i;

              if (高烧 > 95) {
if (BoilEvent != null) { 条件有客体招收
                      BoilEvent(高烧);  使转变有招收客体的办法
                  }
}
}
}
}

    // 警报器
    publicclassAlarm {
publicvoid MakeAlert(int 决定因素) {
Console听听听听听听听听听听听听听“Alarm:哔哔声,水曾经 {0} 度了:”, 决定因素);
}
}

    // 仔细研究
    publicclassDisplay {
publicstaticvoid ShowMsg(int 决定因素) { //恒稳态办法
           Console听听听听听听听听听听听听听“Display:水在激起。,礼物高烧:{0}度。”, 决定因素);
}
}
classProgram {
staticvoidMain() {
Heater heater = newHeater();
Alarm alarm = newAlarm();

           heater.BoilEvent += ;    //招收办法
           heater.BoilEvent += (new Alarm()).MakeAlert;   隐姓埋名客体招收办法
           heater.BoilEvent += Display.ShowMsg;       招收恒稳态办法

();   //烧水,志愿地使转变招收客体的办法
       }
}
}
出口为:
Alarm:哔哔声,水曾经 96 度了:
Alarm:哔哔声,水曾经 96 度了:
Display:水在激起。,礼物高烧:96度。
// 省略.

.Net Framework说得中肯付托与事件

尽管如此上面的样本十足好,可以做本人想做的事实。,但本人不只仅是困惑茫然的。:为什么.Net Framework 说得中肯事件性格和上面的不同的?为什么有很多的EventArgs决定因素?

在回复前文成绩预先阻止,本人率先听说 .Net 边框行为准则眼镜:

  • 付托典型的据以取名可能与EventHandler。
  • 付托的典型限度局限:较慈祥的钟奈何又来值。,并接到两个输出决定因素:稍许的钟客体 典型,稍许的钟 EventArgs典型(或增殖自EventArgs)。
  • 事件的命名为 付托了 剩的有些因EventHandler。
  • 典型增殖自EventArgs可能完毕的事件。

作离题话的解说:

  1. 在付托表现典型代表的客体典型的决定因素,也执意测定客体,在这种情况下,它是 采暖器(热水器)。回调重大聚会(譬如Alarm的MakeAlert)可以因它逗留春季事件的客体(Heater)。
  2. EventArgs 客体克制鉴定书员感兴趣的消息。,在这种情况下,它是temperature。

这些不只仅是用于编码眼镜。,这也使得次更易被说服的。。譬如说,条件本人小病通用热水器的高烧,也期望在鉴定书端(警报或显示)取得它的出厂日期。、模式、价钱,这样,布道所和办法的表现适合不常见的讨厌的人。,条件本人把热水器的援用传给告警器,热水器可以直截了当地进入该办法。。

如今本人重写了后面的样本。,让它调节眼球的晶状体 .Net Framework 的眼镜:

using System;
using System.Collections.Generic;
using System.Text;

namespace Delegate {
// 热水器
    publicclassHeater {
privateint temperature;
publicstring type = “RealFire 001”;       // 添加性格作为演示
       publicstring area = “China Xian”;         // 增殖产地作为以身作则
       海关放行付托书
       publicdelegatevoid BoiledEventHandler(Object sender, BoiledEventArgs e);
publiceventBoiledEventHandler Boiled; //表现事件

// boiledeventargs类限度局限,使分娩给鉴定书员的数据
       publicclassBoiledEventArgs : EventArgs {
publicreadonlyint temperature;
public BoiledEventArgs(int 高烧) {
this.temperature = temperature;
}
}

       // 可以增殖 Heater 类重写,这样增殖类回绝由另一个客体监督它。
       protectedvirtualvoid OnBoiled(煮EventArgs e) {
if (煮 != null) { // 条件有客体招收
              Boiled(this, e);  // 使转变有招收客体的办法
           }
}
// 烧水。
       publicvoid BoilWater() {
for (int i = 0; i <= 100; i++) {
temperature = i;
if (高烧 > 95) {
树立boiledeventargs 客体。
                  BoiledEventArgs e = new BoiledEventArgs(高烧);
OnBoiled(e);  // 使转变 OnBolied办法
              }
}
}
}

    // 警报器
    publicclassAlarm {
publicvoid MakeAlert(Object sender, Heater.BoiledEventArgs e) {
Heater heater = (采暖器)发送器 在这里熟习吗?
           //逗留 sender 郊野里的公共田地
           Console听听听听听听听听听听听听听“Alarm:{0} – {1}: “, heater.area, heater.type);
Console听听听听听听听听听听听听听“Alarm: 哔哔声,水曾经 {0} 度了:”, );
Console听听听听听听听听听听听听听);
}
}

    // 仔细研究
    publicclassDisplay {
publicstaticvoid ShowMsg(Object sender, Heater.BoiledEventArgs e) {   //恒稳态办法
           Heater heater = (采暖器)发送器
Console听听听听听听听听听听听听听“Display:{0} – {1}: “, heater.area, heater.type);
Console听听听听听听听听听听听听听“Display:水在激起。,礼物高烧:{0}度。”, );
Console听听听听听听听听听听听听听);
}
}

    classProgram {
staticvoid Main() {
Heater heater = newHeater();
Alarm alarm = newAlarm();

           heater.Boiled += ;   //招收办法
           heater.Boiled += (new Alarm()).MakeAlert;      隐姓埋名客体招收办法
           heater.Boiled += new Heater.BoiledEventHandler();    你也可以招收这么地
           heater.Boiled += Display.ShowMsg;       招收恒稳态办法

();   //烧水,志愿地使转变招收客体的办法
       }
}
}

出口为:
Alarm:China Xian – RealFire 001:
Alarm: 哔哔声,水曾经 96 度了:
Alarm:China Xian – RealFire 001:
Alarm: 哔哔声,水曾经 96 度了:
Alarm:China Xian – RealFire 001:
Alarm: 哔哔声,水曾经 96 度了:
Display:China Xian – RealFire 001:
Display:水在激起。,礼物高烧:96度。
// 省略

总结

在本贴壁纸我率先因稍许的钟GreetingPeople的小次向大伙儿引见了付托的模糊想法、付托是用来做又诸如此类?,随后又博得了事件,被卡住对付托与事件所发生的胸部行为准则做了粗略的详细叙述。

以离题话的个有点儿复杂的热水器为例,我给你做了简略的引见。 Observer设计状况,因造成这么地性格曾经成功了这么地状况。,与它告知。 付托边框、事件的造成方法。

我期望冠词能对你有所帮忙。。


RSS feed for comments on this post · TrackBack URI

Leave a reply