最近在学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. maven配置多个镜像

    问题场景 1.国内访问maven默认远程中央镜像特别慢 2.用阿里的镜像替代远程中央镜像 3.大部分jar包都可以在阿里镜像中找到,部分jar包在阿里镜像中没有,需要单独配置镜像 解决方案 setti ...

  2. Oracle 11gR2中HR用户安装说明

    1.脚本下载: 链接: 1,脚本放在这个目录下$ORACLE_HOME/demo/schema/human_resources             hr_analz.sql  hr_code.sq ...

  3. 荧屏弹幕_新增h5requestAnimationFrame实现

    所有的页面逻辑也是比较简单,用原生js实现,封装也是比较简单!要让页面效果更为炫酷,则可去引入相应的css,背景图片自己去img/下下载引入喔! HTML页面 <!doctype html> ...

  4. Maven項目打包報錯:Plugin execution not covered by lifecycle configuration

    Maven項目打包報錯:Plugin execution not covered by lifecycle configuration 使用Eclipse导入一个新的maven项目时不时的会遇到这个错 ...

  5. 查看SpringBoot应用中的嵌入式tomcat的版本

    第一种,在启动springboot项目的时候,日志中可以看到 第二种,直接在maven依赖文件中查看 地址在:你的maven库文件夹/org/springframework/boot/spring-b ...

  6. .Net Core 3.0后台使用httpclient请求网络网页和图片_使用Core3.0做一个简单的代理服务器

    目标:使用.net core最新的3.0版本,借助httpclient和本机的host域名代理,实现网络请求转发和内容获取,最终显示到目标客户端! 背景:本人在core领域是个新手,对core的使用不 ...

  7. Python实现图片的base64编码

    import base64 if __name__ == "__main__": dir='image.jpg' basef=open(dir.split('.')[0]+'_ba ...

  8. tomcat8 到idea控制台和servlet乱码问题

    作者:晨钟暮鼓c个人微信公众号:程序猿的月光宝盒 1.问题重现 ​ Tomcat8 部署到idea上时候,控制台出现的乱码 如图,本来框出来的是乱码 其中,"测试"这个是在serv ...

  9. Go-数据类型以及变量,常量

    一.数据类型 1.字符串类型 string 2.数字类型 有符号整型: int: int 在32位机器上是int32 在64位机器是int64 int8: int8 表示数字范围是 正负2的7次方减1 ...

  10. css网页布局模板

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...