陈玉芳 發表於 2020-6-30 09:26:00

C# 从1到Core--委托与事件

<p>  委托与事件在C#1.0的时候就有了,随着C#版本的不断更新,有些写法和功能也在不断改变。本文温故一下这些改变,以及在NET Core中关于事件的一点改变。</p>
<h1>一、C#1.0&nbsp;从委托开始</h1>
<h2>1. 基本方式</h2>
<p>  什么是委托,就不说概念了,用例子说话。</p>
<p>  某HR说他需要招聘一个6年 .NET5 研发经验的“高级”工程师,他想找人(委托)别人把这条招聘消息发出去。这样的HR很多,所以大家定义了一个通用的发消息规则:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">string</span> SendDelegate(<span style="color: rgba(0, 0, 255, 1)">string</span> message);</pre>
</div>
<p>  这就像一个接口的方法,没有实际的实现代码,只是定义了这个方法有一个string的参数和返回值。所有想发招聘消息的HR只要遵守这样的规则即可。</p>
<p>委托本质上是一个类,所以它可以被定义在其他类的内部或外部,根据实际引用关系考虑即可。本例单独定义在外部。</p>
<p>为HR定义了一个名为HR的类:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> HR
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> SendDelegate sendDelegate;
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> SendMessage(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> msg)
    {
      sendDelegate(msg);
    }
}</span></pre>
</div>
<p>  HR有一个SendDelegate类型的成员,当它需要发送消息(SendMessage)的时候,只需要调用这个sendDelegate方法即可。而不需要实现这个方法,也不需要关心这个方法是怎么实现的。</p>
<p>当知道这个HR需要发送消息的时候,猎头张三接了这个帮忙招人的工作。猎头的类为Sender,他有一个用于发送消息的方法Send,该方法恰好符合众人定义的名为SendDelegate的发消息规则。这有点像实现了一个接口方法,但这里不要求方法名一致,只是要求方法的签名一致。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Sender
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> Sender(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> name)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">this</span>.senderName =<span style="color: rgba(0, 0, 0, 1)"> name;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">readonly</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> senderName;
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span> Send(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> message)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">string</span> serialNumber =<span style="color: rgba(0, 0, 0, 1)"> Guid.NewGuid().ToString();
      Console.WriteLine(senderName </span>+ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> sending....</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Thread.Sleep(</span><span style="color: rgba(128, 0, 128, 1)">2000</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Sender: </span><span style="color: rgba(128, 0, 0, 1)">"</span> + senderName + <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> , Content: </span><span style="color: rgba(128, 0, 0, 1)">"</span> + message + <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">, Serial Number: </span><span style="color: rgba(128, 0, 0, 1)">"</span>+<span style="color: rgba(0, 0, 0, 1)"> serialNumber);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> serialNumber;
    }
}</span></pre>
</div>
<p>猎头帮助HR招人的逻辑如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Test()
{
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">一个HR</span>
    HR hr = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> HR();

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">猎头张三来监听,听到HR发什么消息后立刻传播出去</span>
    Sender senderZS = <span style="color: rgba(0, 0, 255, 1)">new</span> Sender(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">张三</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);</span>
    hr.sendDelegate =<span style="color: rgba(0, 0, 0, 1)"> senderZS.Send;<br><br></span><span style="color: rgba(0, 128, 0, 1)">    //HR</span><span style="color: rgba(0, 128, 0, 1)">递交消息</span>
    hr.SendMessage(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Hello World</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);</span><span style="color: rgba(0, 0, 0, 1)">
}</span></pre>
</div>
<p>猎头将自己的发消息方法“赋值”给了HR的SendDelegate方法,为什么可以“赋值”? 因为二者都遵守SendDelegate规则。 就像A和B两个变量都是int类型的时候,A可以赋值给B一样。</p>
<p>这就是一个简单的委托过程,HR将招人的工作委托给了猎头,自己不用去做招人的工作。</p>
<p>但经常一个招聘工作经常会有多个猎头接单,那就有了多播委托。</p>
<h2>2. 多播委托</h2>
<p>&nbsp;看一下下面的代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Test()
{
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">一个HR</span>
    HR hr = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> HR();

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">猎头张三来监听,听到HR发什么消息后立刻传播出去</span>
    Sender senderZS = <span style="color: rgba(0, 0, 255, 1)">new</span> Sender(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">张三</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);</span>
    hr.sendDelegate =<span style="color: rgba(0, 0, 0, 1)"> senderZS.Send;

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">快嘴李四也来了</span>
    Sender senderLS = <span style="color: rgba(0, 0, 255, 1)">new</span> Sender(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">李四</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    hr.sendDelegate </span>+=<span style="color: rgba(0, 0, 0, 1)"> senderLS.Send;<br>
</span><span style="color: rgba(0, 128, 0, 1)">    //HR</span><span style="color: rgba(0, 128, 0, 1)">递交消息</span>
    hr.SendMessage(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Hello World</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);</span><span style="color: rgba(0, 0, 0, 1)">
}</span></pre>
</div>
<p>与之前的代码改变不大, 只是添加了李四的方法绑定,这样HR发消息的时候,张三和李四都会发出招人的消息。</p>
<p>这里要注意李四绑定方法的时候,用的是+=而不是=,就像拼接字符串一样,是拼接而不是赋值,否则会覆盖掉之前张三的方法绑定。</p>
<p>对于第一个绑定的张三,可以用=号也可以用+=(记得之前好像第一个必须用=,实验了一下现在二者皆可)。</p>
<p>这同时也暴露了一些问题:</p>
<ul>
<li>如果后面的猎头接单的时候不小心(故意)用了=号, 那么最终前面的人的绑定都没有了,那么他将独占这个HR客户,HR发出的消息只有他能收到。</li>
<li>可以偷偷的调用猎头的hr.sendDelegate</li>
</ul>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Test()
{
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">一个HR</span>
    HR hr = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> HR();

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">大嘴张三来监听,听到HR发什么消息后立刻传播出去</span>
    Sender senderZS = <span style="color: rgba(0, 0, 255, 1)">new</span> Sender(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">张三</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">hr.sendDelegate -= senderZS.Send; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">即使未进行过+=直接调用-=,也不会报错</span>
    hr.sendDelegate +=<span style="color: rgba(0, 0, 0, 1)"> senderZS.Send;

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">快嘴李四也来了</span>
    Sender senderLS = <span style="color: rgba(0, 0, 255, 1)">new</span> Sender(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">李四</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    hr.sendDelegate </span>+=<span style="color: rgba(0, 0, 0, 1)"> senderLS.Send;

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">移除
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">hr.sendDelegate -= senderZS.Send;

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">风险:注意上面用的符号是+=和-=   如果使用=,则是赋值操作,
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">例如下面的语句会覆盖掉之前所有的绑定
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">hr.sendDelegate = senderWW.Send;

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">HR递交消息</span>
    hr.SendMessage(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Hello World</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">风险:可以偷偷的以HR的名义偷偷的发了一条消息    sendDelegate应该只能由HR调用   </span>
    hr.sendDelegate(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">偷偷的发一条</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

}</span></pre>
</div>
<h2>3. 通过方法避免风险</h2>
<p>  很自然想到采用类似Get和Set的方式避免上面的问题。既然委托可以像变量一样赋值,那么也可以通过参数来传值,将一个方法作为参数传递。</p>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> HRWithAddRemove
    {
      </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> SendDelegate sendDelegate;

      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> AddDelegate(SendDelegate sendDelegate)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">this</span>.sendDelegate += sendDelegate; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如果需要限制最多绑定一个,此处可以用=号</span>
<span style="color: rgba(0, 0, 0, 1)">      }

      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> RomoveDelegate(SendDelegate sendDelegate)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">this</span>.sendDelegate -=<span style="color: rgba(0, 0, 0, 1)"> sendDelegate;
      }

      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> SendMessage(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> msg)
      {
            sendDelegate(msg);
      }
    }</span></pre>
</div>
<p>经过改造后的HR,SendDelegate方法被设置为了private,之后只能通过Add和Remove的方法进行方法绑定。</p>
<h2>4.模拟多播委托机制</h2>
<p>通过上面委托的表现来看,委托就像是保存了一个相同方法名的集合&nbsp;<span class="cnblogs_code">List&lt;SendDelegate&gt;</span>&nbsp;,可以向集合中添加或移除方法,当调用这个委托的时候,会逐一调用该集合中的各个方法。</p>
<p>例如下面的代码( <span style="color: rgba(255, 102, 0, 1)">注意这里假设SendDelegate只对应一个方法</span>&nbsp;):</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> HR1
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Delegate(SendDelegate sendDelegate)
    {
      sendDelegateList </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> List&lt;SendDelegate&gt; { sendDelegate }; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">对应=</span>
<span style="color: rgba(0, 0, 0, 1)">    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> AddDelegate(SendDelegate sendDelegate)
    {
      sendDelegateList.Add(sendDelegate); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">对应+=</span>
<span style="color: rgba(0, 0, 0, 1)">    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> RomoveDelegate(SendDelegate sendDelegate)
    {
      sendDelegateList.Remove(sendDelegate);</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">对应-=</span>
<span style="color: rgba(0, 0, 0, 1)">    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> List&lt;SendDelegate&gt;<span style="color: rgba(0, 0, 0, 1)"> sendDelegateList;

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> SendMessage(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> msg)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> item <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> sendDelegateList)
      {
            item(msg);
      }
    }
}</span></pre>
</div>
<h1>二、C#1.0&nbsp;引入事件</h1>
<h2>  1.简单事件</h2>
<p>  如果既想使用-=和+=的方便,又想避免相关功能开闭的风险怎么办呢?可以使用事件:</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> HRWithEvent
    {
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">event</span><span style="color: rgba(0, 0, 0, 1)"> SendDelegate sendDelegate;
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> SendMessage(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> msg)
      {
            sendDelegate(msg);
      }
    }</span></pre>
</div>
<p>  只是将SendDelegate前面添加了一个event标识,虽然它被设置为public,但如下代码却会给出错误提示:&nbsp;<span style="color: rgba(255, 102, 0, 1)">事件“HRWithEvent.sendDelegate”只能出现在 += 或 -= 的左边(从类型“HRWithEvent”中使用时除外)&nbsp;</span></p>
<div class="cnblogs_code">
<pre> hr.sendDelegate =<span style="color: rgba(0, 0, 0, 1)"> senderZS.Send;
hr.sendDelegate(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">偷偷的发一条</span><span style="color: rgba(128, 0, 0, 1)">"</span>);</pre>
</div>
<h2>  2.事件的访问器模式</h2>
<p>&nbsp;  上文为委托定义了Add和Remove方法,而事件支持这样的访问器模式,例如如下代码:</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> CustomerWithEventAddRemove
    {
      </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">event</span><span style="color: rgba(0, 0, 0, 1)"> SendDelegate sendDelegate;

      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">event</span><span style="color: rgba(0, 0, 0, 1)"> SendDelegate SendDelegate
      {
            add { sendDelegate </span>+=<span style="color: rgba(0, 0, 0, 1)"> value; }
            remove { sendDelegate </span>-=<span style="color: rgba(0, 0, 0, 1)"> value; }
      }
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> SendMessage(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> msg)
      {
            sendDelegate(msg);
      }
    }</span></pre>
</div>
<p>&nbsp;</p>
<p>  可以像使用Get和Set方法一样,对事件的绑定与移除进行条件约束。&nbsp;</p>
<h2>  3. 控制绑定事件的执行</h2>
<p>  当多个委托被绑定到事件之后,如果想精确控制各个委托的运行怎么办,比如返回值(虽然经常为void)、异常处理等。</p>
<p>第一章第4节通过一个List&lt;SendDelegate&gt; 模拟了多播委托的绑定。 会想到如果真能循环调用一个个已绑定的委托,就可以精确的进行控制了。那么这里说一下这样的方法:</p>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> HRWithEvent
    {
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">event</span><span style="color: rgba(0, 0, 0, 1)"> SendDelegate sendDelegate;
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> SendMessage(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> msg)
      {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">sendDelegate(msg);此处不再一次性调用所有</span>
            <span style="color: rgba(0, 0, 255, 1)">if</span> (sendDelegate != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
            {
                Delegate[] delegates </span>= sendDelegate.GetInvocationList(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取所有已绑定的委托</span>
                <span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> item <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> delegates)
                {
                  ((SendDelegate)item).Invoke(msg); <span style="color: rgba(51, 153, 102, 1)">//逐一调用</span></span><span style="color: rgba(0, 0, 0, 1)">
                }
            }

      }
    }</span></pre>
</div>
<p>  这里通过Invoke方法逐一调用各个Delegate,从而实现对每一个Delegate的调用的控制。若需要异步调用,则可以通过BeginInvoke方法实现<span style="color: rgba(255, 0, 0, 1)">(.NET Core之后不再支持此方法,后面会介绍。)</span></p>
<div class="cnblogs_code">
<pre>((SendDelegate)item).BeginInvoke(msg,<span style="color: rgba(0, 0, 255, 1)">null</span>,<span style="color: rgba(0, 0, 255, 1)">null</span>);</pre>
</div>
<h2>  4. 标准的事件写法</h2>
<p>  .NET 事件委托的标准签名是:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">void</span> OnEventRaised(<span style="color: rgba(0, 0, 255, 1)">object</span> sender, EventArgs args);</pre>
</div>
<p>&nbsp;</p>
<p><span data-ttu-id="a896b-110"><span data-ttu-id="a896b-110">  返回类型为 void。&nbsp;<span data-ttu-id="a896b-111">事件基于委托,而且是多播委托。&nbsp;<span data-ttu-id="a896b-112">参数列表包含两种参数:发件人和事件参数。&nbsp;<span data-ttu-id="a896b-117"><code>sender</code>&nbsp;的编译时类型为&nbsp;<code>System.Object</code><span data-ttu-id="a896b-118">。</span></span></span></span></span></span></p>
<p><span data-ttu-id="a896b-119">  第二种参数通常是派生自&nbsp;<code>System.EventArgs</code>&nbsp;的类型<span style="color: rgba(255, 102, 0, 1)">(<strong>.NET Core 中已不强制要求继承自System.EventArgs,后面会说到)</strong><span data-ttu-id="a896b-120"><span data-ttu-id="a896b-121">。</span></span></span></span></p>
<p><span data-ttu-id="a896b-119"><span data-ttu-id="a896b-120"><span data-ttu-id="a896b-121">  将上面的例子修改一下,改成标准写法,大概是下面代码的样子:</span></span></span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> HRWithEventStandard
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">void</span> SendEventHandler(<span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)"> sender, SendMsgArgs e);
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">event</span><span style="color: rgba(0, 0, 0, 1)"> SendEventHandler Send;
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> SendMessage(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> msg)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">var</span> arg = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SendMsgArgs(msg);
      Send(</span><span style="color: rgba(0, 0, 255, 1)">this</span>,arg); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">arg.CancelRequested 为最后一个的值   因为覆盖</span>
<span style="color: rgba(0, 0, 0, 1)">    }
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> SendMsgArgs : EventArgs
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">readonly</span> <span style="color: rgba(0, 0, 255, 1)">string</span> Msg = <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">.Empty;
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">bool</span> CancelRequested { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> SendMsgArgs(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> msg)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">this</span>.Msg =<span style="color: rgba(0, 0, 0, 1)"> msg;
    }
}</span></pre>
</div>
<p>&nbsp;</p>
<p><span data-ttu-id="a896b-110"><span data-ttu-id="a896b-111"><span data-ttu-id="a896b-112"><span data-ttu-id="a896b-113"><span data-ttu-id="a896b-114"><span data-ttu-id="a896b-115">&nbsp;</span></span></span></span></span></span></p>
<h1>三、随着C#版本改变</h1>
<h2>1. C#2.0 泛型委托</h2>
<p>  C#2.0&nbsp;的时候,随着泛型出现,支持了泛型委托,例如,在委托的签名中可以使用泛型,例如下面代码</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">string</span> SendDelegate&lt;T&gt;(T message);</pre>
</div>
<p>这样的委托适用于不同的参数类型,例如如下代码<span style="color: rgba(255, 102, 0, 1)">(注意使用的时候要对应具体的类型)</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">string</span> SendDelegate&lt;T&gt;<span style="color: rgba(0, 0, 0, 1)">(T message);

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> HR1
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> SendDelegate&lt;<span style="color: rgba(0, 0, 255, 1)">string</span>&gt;<span style="color: rgba(0, 0, 0, 1)"> sendDelegate1;
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> SendDelegate&lt;<span style="color: rgba(0, 0, 255, 1)">int</span>&gt;<span style="color: rgba(0, 0, 0, 1)"> sendDelegate2;
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> SendDelegate&lt;DateTime&gt;<span style="color: rgba(0, 0, 0, 1)"> sendDelegate3;
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Sender1
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">string</span> Send1(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> msg)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">string</span> Send2(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> msg)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">;
    }
}
   
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Test
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> TestDemo()
    {
      HR1 hr1 </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> HR1();
      hr1.sendDelegate1 </span>= Sender1.Send1; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 注意使用的时候要对应具体的类型</span>
      hr1.sendDelegate2 = <span style="color: rgba(0, 0, 255, 1)">new</span> SendDelegate&lt;<span style="color: rgba(0, 0, 255, 1)">int</span>&gt;<span style="color: rgba(0, 0, 0, 1)">(Sender1.Send2);
      hr1.sendDelegate3 </span>= <span style="color: rgba(0, 0, 255, 1)">delegate</span> (DateTime dateTime) { <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> dateTime.ToLongDateString(); };

    }
}</span></pre>
</div>
<h2>2. C#2.0 delegate运算符</h2>
<p><code>delegate</code>&nbsp;运算符创建一个可以转换为委托类型的匿名方法:</p>
<p>例如上例中这样的代码:</p>
<div class="cnblogs_code">
<pre>hr1.sendDelegate3 = <span style="color: rgba(0, 0, 255, 1)">delegate</span> (DateTime dateTime) { <span style="color: rgba(0, 0, 255, 1)">return</span> dateTime.ToLongDateString(); };</pre>
</div>
<h2>3. C#3.0&nbsp;<span data-ttu-id="f161a-102">Lambda 表达式</span></h2>
<p><span data-ttu-id="34c81-104">从 C# 3 开始,lambda 表达式提供了一种更简洁和富有表现力的方式来创建匿名函数。&nbsp;<span data-ttu-id="34c81-105">使用&nbsp;=&gt; 运算符构造 lambda 表达式,</span></span></p>
<p><span data-ttu-id="34c81-104"><span data-ttu-id="34c81-105">例如“</span></span>delegate运算符”的例子可以简化为如下代码:</p>
<div class="cnblogs_code">
<pre>hr1.sendDelegate3 = (dateTime) =&gt; { <span style="color: rgba(0, 0, 255, 1)">return</span> dateTime.ToLongDateString(); };</pre>
</div>
<p>&nbsp;</p>
<h2>4.C#3,NET Framework3.5,Action 、Func、Predicate</h2>
<p>Action 、Func、Predicate本质上是框架为我们预定义的委托,在上面的例子中,我们使用委托的时候,首先要定义一个委托类型,然后在实际使用的地方使用,而使用委托只要求方法名相同,在泛型委托出现之后,“定义委托”这一操作就显得越来越累赘,为此,系统为我们预定义了一系列的委托,我们只要使用即可。</p>
<p>例如Action的代码如下:</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Action();
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Action&lt;<span style="color: rgba(0, 0, 255, 1)">in</span> T&gt;<span style="color: rgba(0, 0, 0, 1)">(T obj);
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Action&lt;<span style="color: rgba(0, 0, 255, 1)">in</span> T1, <span style="color: rgba(0, 0, 255, 1)">in</span> T2&gt;<span style="color: rgba(0, 0, 0, 1)">(T1 arg1, T2 arg2);
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Action&lt;<span style="color: rgba(0, 0, 255, 1)">in</span> T1, <span style="color: rgba(0, 0, 255, 1)">in</span> T2, <span style="color: rgba(0, 0, 255, 1)">in</span> T3&gt;<span style="color: rgba(0, 0, 0, 1)">(T1 arg1, T2 arg2, T3 arg3);
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Action&lt;<span style="color: rgba(0, 0, 255, 1)">in</span> T1, <span style="color: rgba(0, 0, 255, 1)">in</span> T2, <span style="color: rgba(0, 0, 255, 1)">in</span> T3, <span style="color: rgba(0, 0, 255, 1)">in</span> T4&gt;<span style="color: rgba(0, 0, 0, 1)">(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Action&lt;<span style="color: rgba(0, 0, 255, 1)">in</span> T1, <span style="color: rgba(0, 0, 255, 1)">in</span> T2, <span style="color: rgba(0, 0, 255, 1)">in</span> T3, <span style="color: rgba(0, 0, 255, 1)">in</span> T4, <span style="color: rgba(0, 0, 255, 1)">in</span> T5&gt;<span style="color: rgba(0, 0, 0, 1)">(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Action&lt;<span style="color: rgba(0, 0, 255, 1)">in</span> T1, <span style="color: rgba(0, 0, 255, 1)">in</span> T2, <span style="color: rgba(0, 0, 255, 1)">in</span> T3, <span style="color: rgba(0, 0, 255, 1)">in</span> T4, <span style="color: rgba(0, 0, 255, 1)">in</span> T5, <span style="color: rgba(0, 0, 255, 1)">in</span> T6&gt;<span style="color: rgba(0, 0, 0, 1)">(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Action&lt;<span style="color: rgba(0, 0, 255, 1)">in</span> T1, <span style="color: rgba(0, 0, 255, 1)">in</span> T2, <span style="color: rgba(0, 0, 255, 1)">in</span> T3, <span style="color: rgba(0, 0, 255, 1)">in</span> T4, <span style="color: rgba(0, 0, 255, 1)">in</span> T5, <span style="color: rgba(0, 0, 255, 1)">in</span> T6, <span style="color: rgba(0, 0, 255, 1)">in</span> T7&gt;<span style="color: rgba(0, 0, 0, 1)">(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Action&lt;<span style="color: rgba(0, 0, 255, 1)">in</span> T1, <span style="color: rgba(0, 0, 255, 1)">in</span> T2, <span style="color: rgba(0, 0, 255, 1)">in</span> T3, <span style="color: rgba(0, 0, 255, 1)">in</span> T4, <span style="color: rgba(0, 0, 255, 1)">in</span> T5, <span style="color: rgba(0, 0, 255, 1)">in</span> T6, <span style="color: rgba(0, 0, 255, 1)">in</span> T7, <span style="color: rgba(0, 0, 255, 1)">in</span> T8&gt;<span style="color: rgba(0, 0, 0, 1)">(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Action&lt;<span style="color: rgba(0, 0, 255, 1)">in</span> T1, <span style="color: rgba(0, 0, 255, 1)">in</span> T2, <span style="color: rgba(0, 0, 255, 1)">in</span> T3, <span style="color: rgba(0, 0, 255, 1)">in</span> T4, <span style="color: rgba(0, 0, 255, 1)">in</span> T5, <span style="color: rgba(0, 0, 255, 1)">in</span> T6, <span style="color: rgba(0, 0, 255, 1)">in</span> T7, <span style="color: rgba(0, 0, 255, 1)">in</span> T8, <span style="color: rgba(0, 0, 255, 1)">in</span> T9&gt;<span style="color: rgba(0, 0, 0, 1)">(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9);
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Action&lt;<span style="color: rgba(0, 0, 255, 1)">in</span> T1, <span style="color: rgba(0, 0, 255, 1)">in</span> T2, <span style="color: rgba(0, 0, 255, 1)">in</span> T3, <span style="color: rgba(0, 0, 255, 1)">in</span> T4, <span style="color: rgba(0, 0, 255, 1)">in</span> T5, <span style="color: rgba(0, 0, 255, 1)">in</span> T6, <span style="color: rgba(0, 0, 255, 1)">in</span> T7, <span style="color: rgba(0, 0, 255, 1)">in</span> T8, <span style="color: rgba(0, 0, 255, 1)">in</span> T9, <span style="color: rgba(0, 0, 255, 1)">in</span> T10&gt;<span style="color: rgba(0, 0, 0, 1)">(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10);
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Action&lt;<span style="color: rgba(0, 0, 255, 1)">in</span> T1, <span style="color: rgba(0, 0, 255, 1)">in</span> T2, <span style="color: rgba(0, 0, 255, 1)">in</span> T3, <span style="color: rgba(0, 0, 255, 1)">in</span> T4, <span style="color: rgba(0, 0, 255, 1)">in</span> T5, <span style="color: rgba(0, 0, 255, 1)">in</span> T6, <span style="color: rgba(0, 0, 255, 1)">in</span> T7, <span style="color: rgba(0, 0, 255, 1)">in</span> T8, <span style="color: rgba(0, 0, 255, 1)">in</span> T9, <span style="color: rgba(0, 0, 255, 1)">in</span> T10, <span style="color: rgba(0, 0, 255, 1)">in</span> T11&gt;<span style="color: rgba(0, 0, 0, 1)">(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11);
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Action&lt;<span style="color: rgba(0, 0, 255, 1)">in</span> T1, <span style="color: rgba(0, 0, 255, 1)">in</span> T2, <span style="color: rgba(0, 0, 255, 1)">in</span> T3, <span style="color: rgba(0, 0, 255, 1)">in</span> T4, <span style="color: rgba(0, 0, 255, 1)">in</span> T5, <span style="color: rgba(0, 0, 255, 1)">in</span> T6, <span style="color: rgba(0, 0, 255, 1)">in</span> T7, <span style="color: rgba(0, 0, 255, 1)">in</span> T8, <span style="color: rgba(0, 0, 255, 1)">in</span> T9, <span style="color: rgba(0, 0, 255, 1)">in</span> T10, <span style="color: rgba(0, 0, 255, 1)">in</span> T11, <span style="color: rgba(0, 0, 255, 1)">in</span> T12&gt;<span style="color: rgba(0, 0, 0, 1)">(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12);
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Action&lt;<span style="color: rgba(0, 0, 255, 1)">in</span> T1, <span style="color: rgba(0, 0, 255, 1)">in</span> T2, <span style="color: rgba(0, 0, 255, 1)">in</span> T3, <span style="color: rgba(0, 0, 255, 1)">in</span> T4, <span style="color: rgba(0, 0, 255, 1)">in</span> T5, <span style="color: rgba(0, 0, 255, 1)">in</span> T6, <span style="color: rgba(0, 0, 255, 1)">in</span> T7, <span style="color: rgba(0, 0, 255, 1)">in</span> T8, <span style="color: rgba(0, 0, 255, 1)">in</span> T9, <span style="color: rgba(0, 0, 255, 1)">in</span> T10, <span style="color: rgba(0, 0, 255, 1)">in</span> T11, <span style="color: rgba(0, 0, 255, 1)">in</span> T12, <span style="color: rgba(0, 0, 255, 1)">in</span> T13&gt;<span style="color: rgba(0, 0, 0, 1)">(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13);
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Action&lt;<span style="color: rgba(0, 0, 255, 1)">in</span> T1, <span style="color: rgba(0, 0, 255, 1)">in</span> T2, <span style="color: rgba(0, 0, 255, 1)">in</span> T3, <span style="color: rgba(0, 0, 255, 1)">in</span> T4, <span style="color: rgba(0, 0, 255, 1)">in</span> T5, <span style="color: rgba(0, 0, 255, 1)">in</span> T6, <span style="color: rgba(0, 0, 255, 1)">in</span> T7, <span style="color: rgba(0, 0, 255, 1)">in</span> T8, <span style="color: rgba(0, 0, 255, 1)">in</span> T9, <span style="color: rgba(0, 0, 255, 1)">in</span> T10, <span style="color: rgba(0, 0, 255, 1)">in</span> T11, <span style="color: rgba(0, 0, 255, 1)">in</span> T12, <span style="color: rgba(0, 0, 255, 1)">in</span> T13, <span style="color: rgba(0, 0, 255, 1)">in</span> T14&gt;<span style="color: rgba(0, 0, 0, 1)">(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14);
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Action&lt;<span style="color: rgba(0, 0, 255, 1)">in</span> T1, <span style="color: rgba(0, 0, 255, 1)">in</span> T2, <span style="color: rgba(0, 0, 255, 1)">in</span> T3, <span style="color: rgba(0, 0, 255, 1)">in</span> T4, <span style="color: rgba(0, 0, 255, 1)">in</span> T5, <span style="color: rgba(0, 0, 255, 1)">in</span> T6, <span style="color: rgba(0, 0, 255, 1)">in</span> T7, <span style="color: rgba(0, 0, 255, 1)">in</span> T8, <span style="color: rgba(0, 0, 255, 1)">in</span> T9, <span style="color: rgba(0, 0, 255, 1)">in</span> T10, <span style="color: rgba(0, 0, 255, 1)">in</span> T11, <span style="color: rgba(0, 0, 255, 1)">in</span> T12, <span style="color: rgba(0, 0, 255, 1)">in</span> T13, <span style="color: rgba(0, 0, 255, 1)">in</span> T14, <span style="color: rgba(0, 0, 255, 1)">in</span> T15&gt;<span style="color: rgba(0, 0, 0, 1)">(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15);
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Action&lt;<span style="color: rgba(0, 0, 255, 1)">in</span> T1, <span style="color: rgba(0, 0, 255, 1)">in</span> T2, <span style="color: rgba(0, 0, 255, 1)">in</span> T3, <span style="color: rgba(0, 0, 255, 1)">in</span> T4, <span style="color: rgba(0, 0, 255, 1)">in</span> T5, <span style="color: rgba(0, 0, 255, 1)">in</span> T6, <span style="color: rgba(0, 0, 255, 1)">in</span> T7, <span style="color: rgba(0, 0, 255, 1)">in</span> T8, <span style="color: rgba(0, 0, 255, 1)">in</span> T9, <span style="color: rgba(0, 0, 255, 1)">in</span> T10, <span style="color: rgba(0, 0, 255, 1)">in</span> T11, <span style="color: rgba(0, 0, 255, 1)">in</span> T12, <span style="color: rgba(0, 0, 255, 1)">in</span> T13, <span style="color: rgba(0, 0, 255, 1)">in</span> T14, <span style="color: rgba(0, 0, 255, 1)">in</span> T15, <span style="color: rgba(0, 0, 255, 1)">in</span> T16&gt;(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16);</pre>
</div>
<p>实际上定义了最多16个参数的无返回值的委托。</p>
<p>Func与此类似,是最多16个参数的有返回值的委托。Predicate则是固定一个参数以及bool类型返回值的委托。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">delegate</span> <span style="color: rgba(0, 0, 255, 1)">bool</span> Predicate&lt;T&gt;(T obj);</pre>
</div>
<h2>&nbsp;5. .NET Core&nbsp;异步调用</h2>
<p>第2.3节中,提示如下代码在.NET Core中已不支持</p>
<div class="cnblogs_code">
<pre>((SendDelegate)item).BeginInvoke(msg,<span style="color: rgba(0, 0, 255, 1)">null</span>,<span style="color: rgba(0, 0, 255, 1)">null</span>);</pre>
</div>
<p>&nbsp;</p>
<p>会抛出异常:</p>
<div class="cnblogs_code">
<pre>System.PlatformNotSupportedException:“Operation <span style="color: rgba(0, 0, 255, 1)">is</span> not supported on <span style="color: rgba(0, 0, 255, 1)">this</span> platform.”</pre>
</div>
<p>&nbsp;</p>
<p>需要异步调用的时候可以采用如下写法:</p>
<div class="cnblogs_code">
<pre>Task task = Task.Run(() =&gt; ((SendDelegate)item).Invoke(msg));</pre>
</div>
<p>&nbsp;</p>
<p>对应的&nbsp;<span class="cnblogs_code">EndInvoke()</span>&nbsp;则改为:&nbsp;<span class="cnblogs_code">task.Wait();</span>&nbsp;</p>
<p>&nbsp;</p>
<h2>&nbsp;5. .NET Core的 EventHandler&lt;TEventArgs&gt;</h2>
<p><span data-ttu-id="523fc-106">.NET Core <span data-ttu-id="523fc-107">版本中,<code>EventHandler&lt;TEventArgs&gt;</code>&nbsp;定义不再要求&nbsp;<code>TEventArgs</code>&nbsp;必须是派生自&nbsp;<code>System.EventArgs</code>&nbsp;的类, 使我们使用起来更为灵活。</span></span></p>
<p><span data-ttu-id="523fc-106"><span data-ttu-id="523fc-107">例如我们可以有这样的写法:</span></span></p>
<div class="cnblogs_code">
<pre>EventHandler&lt;<span style="color: rgba(0, 0, 255, 1)">string</span>&gt; SendNew</pre>
</div>
<p>&nbsp;</p>
<p>这在以前的版本中是不允许的。</p>
<p>&nbsp;</p>

</div>
<div id="MySignature" role="contentinfo">
    ☆☆☆ 共同学习,欢迎拍砖;转载请注明出处,谢谢。欢迎关注我的公众号:闲聊编程。☆☆☆      
<p><img src="https://img2020.cnblogs.com/blog/548134/202005/548134-20200517171550545-1928032874.jpg" alt="" width="79" height="79">&nbsp;</p><br><br>
来源:https://www.cnblogs.com/FlyLolo/p/12879190.html
頁: [1]
查看完整版本: C# 从1到Core--委托与事件