- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章C#委托与事件初探由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
委托给了C#操作函数的灵活性,我们可使用委托像操作变量一样来操作函数,其实这个功能并不是C#的首创,早在C++时代就有函数指针这一说法,而在我看来委托就是C#的函数指针,首先先简要的介绍一下委托的基本知识:
委托的定义 。
委托的声明原型是 。
delegate <函数返回类型> <委托名> (<函数参数>) 。
例子:public delegate void CheckDelegate(int number);//定义了一个委托CheckDelegate,它可以注册返回void类型且有一个int作为参数的函数 。
这样就定义了一个委托,但是委托在.net内相当于声明了一个类(在后面的代码中会讲到确实如此),类如果不实例化为对象,很多功能是没有办法使用的,委托也是如此. 。
委托的实例化 。
委托实例化的原型是 。
<委托类型> <实例化名>=new <委托类型>(<注册函数>) 。
例子:CheckDelegate _checkDelegate=new CheckDelegate(CheckMod);//用函数CheckMod实例化上面的CheckDelegate 委托为_checkDelegate 。
在.net 2.0开始可以直接用匹配的函数实例化委托:
<委托类型> <实例化名>=<注册函数> 。
例子:CheckDelegate _checkDelegate=CheckMod;//用函数CheckMod实例化上面的CheckDelegate 委托为_checkDelegate 现在我们就可以像使用函数一样来使用委托了,在上面的例子中现在执行_checkDelegate()就等同于执行CheckMod(),最关键的是现在函数CheckMod相当于放在了变量当中,它可以传递给其它的CheckDelegate引用对象,而且可以作为函数参数传递到其他函数内,也可以作为函数的返回类型 。
事件是委托的一种特殊形式,当发生有意义的事情时,事件处理对象通知过程.
一.C语言中的函数指针 。
想要理解什么是委托,就要先理解函数指针的概念。所谓函数指针,就是指向函数的指针(等于没说-.-)。比如我定义了两个函数square和cube分别用于计算一个数的平方和立方,我再定义函数指针calcu,然后我让calcu指向square,那么调用calcu时就相当于调用了square函数(注意,此处函数指针接受的参数类型及个数要与函数一致)。很好理解吧?不多说,上代码.
1
2
3
4
5
6
7
8
9
10
|
#include <stdio.h>
void
square(
int
x) { printf(
"square of %d is %d\n"
,x,x*x); }
void
cube(
int
x) { printf(
"cube of %d is %d\n"
,x,x*x*x); }
int
main()
{
void
(*calcu)(
int
x);
calcu=square;
calcu();
return
;
}
|
二.C#中委托的实质 。
委托又名委托类型,为什么C#弄出这个东西?因为C#是一门比较安全的语言,不允许操作指针,于是我们不能定义函数指针。但想要达到相同的效果,于是定义了委托类型。所谓委托类型,其本质就是C中的指针类型。于是代码变成了这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.Threading.Tasks;
namespace
Delegate
{
class
Program
{
static
void
square(
int
x) { Console.WriteLine(
"square of {} is {}"
, x, x * x); }
static
void
cube(
int
x) { Console.WriteLine(
"cube of {} is {}"
, x, x * x * x); }
delegate
void
math(
int
x);
//定义委托类型
static
void
Main(
string
[] args)
{
math calcu;
calcu += square;
calcu();
Console.ReadKey();
}
}
}
|
可以看出,定义委托类型math实际上就相当于定义了void*类型。而委托类型实例化得到的calcu实际上就是函数指针。(说句题外话:定义函数(方法)时要加上static是因为调用函数时并未实例化,只有静态方法能够直接通过类调用).
三.委托的使用方法 。
我们在上述代码19行后面加上一行代码 calcu+=cube; 运行会发现,square和cube均被调用。可以看出,符号 += 表示绑定方法到委托变量,同理符号 -= 表示取消绑定。可以理解为calcu是void **类型,即它指向了一个数组,数组中的每一项都是函数指针类型,每次调用calcu时,遍历此数组,即依次调用每个绑定的方法.
四.封装与事件的引入 。
下面我们要用面向对象的思想将上述代码进行封装,使其变清晰.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.Threading.Tasks;
namespace
Delegate
{
public
delegate
void
math(
int
x);
public
class
Calcu
{
public
math calcu;
}
class
Program
{
static
void
square(
int
x) { Console.WriteLine(
"square of {} is {}"
, x, x * x); }
static
void
cube(
int
x) { Console.WriteLine(
"cube of {} is {}"
, x, x * x * x); }
static
void
Main(
string
[] args)
{
Calcu c =
new
Calcu();
c.calcu += square;
c.calcu += cube;
c.calcu();
Console.ReadKey();
}
}
}
|
由于委托变量是public的,封装的程度很低,在外部可以任意修改。为了改进这个问题,C#引入了事件.
所谓事件,实际上还是委托的实例化,只是其内部多了一些定义,多了一些限制。其一,事件实际上声明了一个private类型的委托变量,因此在类外无法直接调用.
于是我们将上述代码的第12行改成这样:
public event math calcu,
运行之后25行报错了,因为calcu是private的,不能直接调用。但23,24行并没有报错。那么问题来了,为什么我们可以用+=来给calcu绑定方法呢?
因为其二,事件还帮我们干了一件事情,就是定义了绑定方法和取消绑定方法的函数,它们是public的,并且将运算符+=,-=重载,和这两个函数对应.
好了,现在我们要写一个接口函数来完成计算:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.Threading.Tasks;
namespace
Delegate
{
public
delegate
void
math(
int
x);
public
class
Calcu
{
public
event
math calcu;
public
void
calculate(
int
x)
{
calcu(x);
}
}
class
Program
{
static
void
square(
int
x) { Console.WriteLine(
"square of {} is {}"
, x, x * x); }
static
void
cube(
int
x) { Console.WriteLine(
"cube of {} is {}"
, x, x * x * x); }
static
void
Main(
string
[] args)
{
Calcu c =
new
Calcu();
c.calcu += square;
c.calcu += cube;
c.calculate();
Console.ReadKey();
}
}
}
|
至此,基本概念已经清晰.
想来,使用事件会让人不得不将对象封装起来,这应该就是面向对象思想的体现吧.
以上内容是针对C#委托与事件初探的相关知识,希望对大家有所帮助.
最后此篇关于C#委托与事件初探的文章就讲到这里了,如果你想了解更多关于C#委托与事件初探的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在尝试将 WPF CodeBehid 事件(如 Event、Handler、EventSetter)转换为 MVVM 模式。我不允许使用 System.Windows.Controls,因为我使用
我可能误解了 Backbone 中的事件系统,但是当我尝试以下代码时什么也没有发生。当我向 Backbone.Events 扩展对象添加新属性时,它不应该触发某种更改、更新或重置事件吗?就像模型一样吗
我遇到了一个简单的问题,就是无法弄清楚为什么它不起作用。我有一个子组件“app-buttons”,其中我有一个输入字段,我想听,所以我可以根据输入值过滤列表。 如果我将输入放在我有列表的根组件中,一切
System.Timers.Timer 的 Elapsed 事件实际上与 System.Windows.Forms.Timer 的 Tick 事件相同吗? 在特定情况下使用其中一种比使用另一种有优势吗
嗨,这个 javascript 代码段是什么意思。(evt) 部分是如此令人困惑.. evt 不是 bool 值。这个怎么运作? function checkIt(evt) { evt
我正在使用jquery full calendar我试图在事件被删除时保存它。 $('calendar').fullCalendar ({
我有两个链接的鼠标事件: $('body > form').on("mousedown", function(e){ //Do stuff }).on("mouseup", function(
这是我的代码: $( '#Example' ).on( "keypress", function( keyEvent ) { if ( keyEvent.which != 44 ) {
我尝试了 dragOver 事件处理程序,但它没有正常工作。 我正在研究钢琴,我希望能够弹奏音符,即使那个键上没有发生鼠标按下。 是否有事件处理程序? 下面是我正在制作的钢琴的图片。 最佳答案 您应该
当悬停在相邻文本上时,我需要使隐藏按钮可见。这是通过 onMouseEnter 和 onMouseLeave 事件完成的。但是当点击另外的文本时,我需要使按钮完全可见并停止 onMouseLeave
我有ul标签内 div标签。我申请了mouseup事件 div标记和 click事件 ul标签。 问题 每当我点击 ul标签,然后都是 mouseup和 click事件被触发。 我想要的是当我点击 u
我是 Javascript 和 jQuery 的新手,所以我有一个非常愚蠢的疑问,请耐心等待 $(document).click(function () { alert("!"); v
我有一个邮政编码解析器,我正在使用 keyup 事件处理程序来跟踪输入长度何时达到 5,然后查询服务器以解析邮政编码。但是我想防止脚本被不必要地调用,所以我想知道是否有一种方法可以跟踪 keydown
使用事件 API,我有以下代码来发布带有事件照片的事件 $facebook = new Facebook(array( "appId" => "XXX", "se
首次加载 Microsoft Word 时,既不会触发 NewDocument 事件也不会触发 DocumentOpen 事件。当 Word 实例已打开并打开新文档或现有文档时,这些事件会正常触发。
我发现了很多相关问题(这里和其他地方),但还没有具体找到这个问题。 我正在尝试监听箭头键 (37-40) 的按键事件,但是当以特定顺序使用箭头键时,后续箭头不会生成“按键”事件。 例子: http:/
给定的 HTML: 和 JavaScript 的: var $test = $('#test'); $test.on('keydown', function(event) { if (eve
我是 Node.js 的新手,希望使用流运行程序。对于其他程序,我必须同时启动一个服务器(mongodb、redis 等),但我不知道我是否应该用这个运行一个服务器。请让我知道我哪里出了问题以及如何纠
我正在尝试使用 Swift 和 Cocoa 创建一个适用于 OS X 的应用程序。我希望应用程序能够响应关键事件,而不将焦点放在文本字段上/文本字段中。我在 Xcode 中创建了一个带有 Storyb
我有以下代码: (function(w,d,s,l,i){ w[l]=w[l]||[];w[l].push({
我是一名优秀的程序员,十分优秀!