最近在学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. win10配置linux子系统使用python绘图并显示--WSL使用GUI输出

    默认情况下,Win10的linux子系统(WSL)是只能使用命令行程序的.所有图形界面的程序都无法执行. 通过为Win10安装XWindows协议的终端应用,可以让Win10成为一台XWindow终端 ...

  2. fiddler 进行Android/IOS代理配置抓包

    1.准备:Android+IOS设备 下载:fiddler抓包工具,不是最新版的链接:   链接:https://pan.baidu.com/s/1BaBfu2H4xgpsh1wmkfC8aQ     ...

  3. Mybatis基本类型参数非空判断(异常:There is no getter for property...)

    先看一小段代码 <select id="queryByPhone" parameterType="java.lang.String" resultType ...

  4. python 学习 (1-3)

    流程控制if语句 语法种类:   第⼀种语法: if 条件: #引号是将条件与结果分开. 结果1. # 四个空格,或者⼀个tab键,这个是告诉程序满⾜这个条件的 结果2.   如果条件是真(True) ...

  5. Failed to execute ‘createObjectURL’ on ‘URL’: No function was found that matched the signature provided.

    这个报错是因为在浏览器上开启了手机模拟调试.Web SDK 不支持手机模拟调试的.

  6. Kafka简明教程

    作者:柳树之 www.jianshu.com/p/7b77723d4f96 Kafka是啥?用Kafka官方的话来说就是: Kafka is used for building real-time d ...

  7. Java分布式系统---消息中间件

    简介 消息中间件也可以称消息队列,是指用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成.通过提供消息传递和消息队列模型,可以在分布式环境下扩展进程的通信.当下主流 ...

  8. 一文学会JVM性能优化

    实战性能优化 1 重新认知JVM 之前我们画过一张图,是从Class文件到类装载器,再到运行时数据区的过程,现在咱们把这张图不妨丰富完善一下,展示了JVM的大体物理结构图. 执行引擎:用于执行JVM字 ...

  9. mysql登陆时出现ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 0

    有4到5天没开mysql,这天晚上打=打开phpstudy,想进去mysql练习练习,结果丢给我这个 ERROR 2013 (HY000): Lost connection to MySQL serv ...

  10. 简单的jquery表单验证+添加+删除+全选/反选

    //布局 <body> <h4><a href="#">首页</a>><a href="#"> ...