最近在学C#(教材《C# in a nutshell》很不错的说),看完delegate(委托)以后,紧接着就是event(事件)了,个人对跟.Net相关的东西并没有什么兴趣(毕竟是会增加代码复杂度的玩意),可是后面没准用得到,而且讲完.Net那套定义规则之后紧接着就是“接口内定义事件如何实现”,遂想试试写例子看看。

.Net框架下,对于事件对应的委托有三条规则:

1.返回值必须为void——就是没有返回值;

2.参数必须有一个为object——用于转移额外信息(convey extra information),这里也可以用System.EventHandler,但其实EventHandler的说明是“没有额外信息时使用”;

3.名称必须以EventHandler结尾,个人很讨厌Handle这个词,难以解释这是个什么东西,别问,问就句柄,可是句柄又是个什么鬼?(windowsAPI PTSD)

因为没有什么C#的代码经验,所以,并不清楚接口内定义事件的具体应用场合。在不符合以上规则的情况下,

using System;

namespace ForPractise
{
public delegate void MathematicFunc<T>(T e); public interface IFoo { event MathematicFunc<int> InterfaceEvent; } // if .Net use subclass of EventArgs instead of int public class Foo : IFoo
{
private int counter;
private MathematicFunc<int> _field; // private field of delegate
public event MathematicFunc<int> InterfaceEvent // explictly declare add & remove of interface IFoo
{
// ... there could have multiple fields
add { _field += value; }
remove { _field -= value; }
} private void OnBraodcast(int counts) // fire events
{
_field?.Invoke(counts);
} public int Counter
{
get { return counter; }
set
{
if (counter == value)
{
return;
}
counter = value;
OnBraodcast(counter);
}
}
} class Program
{
static int Main()
{
Foo foo = new Foo();
foo.Counter = ;
foo.InterfaceEvent += Multiple;
foo.InterfaceEvent += Ratio;
foo.Counter = ;
foo.InterfaceEvent -= Ratio;
foo.Counter = ;
foo.InterfaceEvent -= Ratio;
foo.InterfaceEvent += Ratio;
foo.Counter = ; Console.Read(); return ;
} static void Multiple(int num)
{
Console.WriteLine("{0} multiply itself {1}", num, num * num);
} static void Ratio(int num)
{
Console.WriteLine("{0} divide 0.1 {1}", num, num / 0.1d);
}
}
}

以上代码中,显示定义event.add跟event.remove可以省略——非必要的(即便显式定义了,在外部也只能通过"+="跟"-="进行订阅),直接写为"public event MathematicFunc<int> interfaceEvent; // 可以加上=null"即可。

下面则是应用.Net规则的代码,会比较肿,套用这种结构,需要额外定义System.EventArgs的子类作为参数,委托在套用泛型的时候也要多加很多东西——不过多参数就可以直接塞到EventArgs的子类里面了,也不清楚是方便了还是糟心了。同上event的显式定义也是非必要的。

using System;

namespace ForPractise
{
public class FooEventArgs : EventArgs
{
public int Counter { set; get; } public FooEventArgs(int count) { Counter = count; }
} public delegate void MathematicEventHandler<TEArgs>(object source, TEArgs e) where TEArgs : EventArgs; // delegate follow the .Net framework three rules public interface IFoo { event MathematicEventHandler<FooEventArgs> InterfaceEvent; } public class Foo : IFoo
{
private int counter;
private MathematicEventHandler<FooEventArgs> _field; // private field of delegate
public event MathematicEventHandler<FooEventArgs> InterfaceEvent // explictly declare add & remove of interface IFoo
{
// ... there could have multiple fields
add { _field += value; }
remove { _field -= value; }
} private void OnBraodcast(FooEventArgs e) // fire events
{
_field?.Invoke(this, e);
} public int Counter
{
get { return counter; }
set
{
if (counter == value)
{
return;
}
counter = value;
OnBraodcast(new FooEventArgs(counter));
}
}
} class Program
{
static int Main()
{
Foo foo = new Foo();
foo.Counter = ;
foo.InterfaceEvent += Multiple;
foo.InterfaceEvent += Ratio;
foo.Counter = ;
foo.InterfaceEvent -= Ratio;
foo.Counter = ;
foo.InterfaceEvent -= Ratio;
foo.InterfaceEvent += Ratio;
foo.Counter = ; Console.Read(); return ;
} static void Multiple(object obj, FooEventArgs e) // will be quite clumsy for simple function methods.
{
Console.WriteLine("{0} multiply itself {1}", e.Counter, e.Counter * e.Counter);
} static void Ratio(object obj, FooEventArgs e)
{
Console.WriteLine("{0} divide 0.1 {1}", e.Counter, e.Counter / 0.1d);
}
}
}

其实MathematicEventHandler这个委托名不以EventHandler结尾依旧可以正常运行,应该是没有放到标准的.Net环境下,不然就是这只是约定俗成的命名法——就跟fire event部分的函数以On做前缀一样。

上面的两段运行结果都是一样的,暂时没找出来差别。还是写简单一些的好呐。

运行结果:

23 multiply itself 529
23 divide 0.1 230
12 multiply itself 144
1 multiply itself 1
1 divide 0.1 10

C# Event在.Net规则下由接口定义的实现的更多相关文章

  1. 注意Vietnamese_CI_AS排序规则下的特殊字符大小敏感问题

    注意Vietnamese_CI_AS排序规则下的特殊字符大小敏感问题   最近,在SQL Server中遇到了Vietnamese_CI_AS排序规则的特殊字符的大小写敏感问题,是的,你没有看错,这句 ...

  2. jmeter将上一个接口返回值作为下一个接口的请求参数

    在jmeter中有时候会用到,将上一个接口的返回值作为下一个接口的请求参数 具体操作如下: 1.首先新建一个http请求(右键线程组--添加Sampler--http请求),同时添加好接口相应的请求参 ...

  3. jmeter将JDBC Request查询出的数据作为下一个接口的参数

    现在有一个需求,从数据库tieba_info表查出rank小于某个值的username和count(*),然后把所有查出来的username和count(*)作为参数值,用于下一个接口. tieba_ ...

  4. was集群下基于接口分布式架构和开发经验谈

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/luozhonghua2014/article/details/34084935    某b项目是我首 ...

  5. 【重点】Jmeter----- 将 JDBC Request 查询结果作为下一个接口参数方法(二)

    一.说明 jmeter与数据库mysql已连接成功 二.需求 1.前置条件: 1.已user数据库的前8位手机号码作为行动计划的名称 2.行动计划的日期是2018-10-17 2.操作步骤: 1)获取 ...

  6. Jmeter将JDBC Request查询结果作为下一个接口参数方法(转载)

    现在有一个需求,从数据库tieba_info表查出rank小于某个值的username和count(*),然后把所有查出来的username和count(*)作为参数值,用于下一个接口. tieba_ ...

  7. 学习笔记---Javascript事件Event、IE浏览器下的拖拽效果

    学习笔记---Javascript事件Event.IE浏览器下的拖拽效果     1. 关于event常用属性有returnValue(是否允许事件处理继续进行, false为停止继续操作).srcE ...

  8. Jmeter将JDBC Request查询结果作为下一个接口参数方法

    现在有一个需求,从数据库tieba_info表查出rank小于某个值的username和count(*),然后把所有查出来的username和count(*)作为参数值,用于下一个接口. tieba_ ...

  9. SpringBoot下支付宝接口的使用

    SpringBoot下支付宝接口的使用 前期准备: 参考之前写过的 支付宝接口引入servlet版本 Jar包引入: <!-- 支付宝 --> <dependency> < ...

随机推荐

  1. MySQL数据库:数据完整性及约束的应用

    数据完整性 1.域完整性:---------匹配完整性:非空.缺省 字段/列 2.实体完整性:-------匹配完整性:主键.唯一键 记录/行 3.引用完整性:-------匹配完整性:外键 表与表之 ...

  2. linux 磁盘分区和挂载看这一篇就够了

    Linux fdisk 和 mount 命令操作指南,linux磁盘管理.新增磁盘.挂载新硬盘(linux运维入门) 首先列出文件系统的整体磁盘空间使用情况.可以用来查看磁盘已被使用多少空间和还剩余多 ...

  3. Linux第二章-Linux常用命令

    一.Linux常用快捷键 快捷键 作用 Tab 补全文件名或者路径 Ctrl + L 清除屏幕,然后,在最上面重新显示目前光标所在的这一行的内容. Ctrl + C 终止当前进程 Ctrl + D 注 ...

  4. Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3

    A,有多个线段,求一条最短的线段长度,能过覆盖到所又线段,例如(2,4)和(5,6) 那么我们需要4 5连起来,长度为1,例如(2,10)(3,11),用(3,10) 思路:我们想一下如果题目说的是最 ...

  5. 第1章 你好,C++并发世界

    #include<iostream> #include<thread> void print(){ std::cout << "hello world&q ...

  6. Centos7下Redis设置开机自启动服务

    有个同事说重启了服务器没有自启动redis,我看了一下,是以前手动编译安装的模式,没有配置开机启动的服务 这边做个笔记记录一下redis如何设置编译安装模式的开机自启动. 第一种方法: 1.编写red ...

  7. 使用pip安装python库的几种方式

    操作系统 : CentOS7.5.1804_x64 Python 版本 : 3.6.8 1.使用pip在线安装 1.1 安装单个package 格式如下: pip install SomePackag ...

  8. Java描述设计模式(07):适配器模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.适配器模式简介 1.基础概念 适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在 ...

  9. PAT 1007 Maximum Subsequence Sum 最大连续子序列和

    Given a sequence of K integers { N1, N2, …, NK }. A continuous subsequence is defined to be { Ni, Ni ...

  10. [IDA] 自动下载符号

    当现实无法自动下载符号时,看下面交互窗口,提示安装 VC++ 2008. 安装成功之后就会自动下载符号.