一、简单的委托

1.1  委托的声明:

  C#当中,委托(delegate)是一种方法封装,也即委托对象可以作为一种传递方法的变量来使用。

  委托也算是一种类,与类是平级的存在。在类中写delegate对象当然是允许的,毕竟C#也允许类中类。但是一般不这样做,委托的声明最好与类声明平级。

  声明:

public  delegate    void         ActionName();

        关键字       返回类型      委托变量名(函数参数)

  方法执行,有两种方式,效果相同:

  TestHandler.Invoke(实参);

  TestHandler(实参);

  示例:

 public delegate void TestHandler(string str);

 class Program
{
static void Main(string[] args)
{
TestHandler t = delegate (string str) { Console.WriteLine($"There will show : {str}"); };
// TestHandler t = str => Console.WriteLine($"There will show : {str}"); lambda表达式,上行的语法糖。
t.Invoke("Hello world !");
}
}

  在说到具体如何实现委托之前,先简单说明一下Action、Func是什么。

  C#规则中,Action和Func都是方法对象(委托类型),两者的区别仅在于有无返回类型。

public delegate void Action();

public delegate TResult Func<out TResult>();

  形参是允许添加多个的:

Action<int, string, double> action
/*============== F12 ================*/
public delegate void Action<in T1, in T2, in T3>(T1 arg1, T2 arg2, T3 arg3);
Func<string, string, string> func
/*============== F12 ================*/
public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2); //(其中,TResult参数总写在形参说明的最后)
// 注:尖括号表示里面是泛型,在声明中,需要在<>内写入具体的类型。

  实例化这个对象,这样写:

Action<T1, T2> action = delegate(T1 arg1, T2 arg2) { 具体实现 };

 类型       变量名称  关键字   (方法入参)          {..}

  例如可以这样声明:

  Action<int, string, double> action = delegate(int a, string b, double c) { };

  Func<string, string, string> func = delegate { return "test.."; };

  注:入参可以省略不写,但是注意可能会有一些小陷阱,见下例[1]:

// 启动新线程,.NET2.0有4个线程构造函数:

public Thread(ParameterizedThreadStart start)

public Thread(ThreadStart start)

public Thread(ParameterizedThreadStart start, int maxStackSize)

public Thread(ThreadStart start, int maxStackSize)

// 涉及的两个委托类型是:

public delegate void ThreadStart()

public delegate void ParameterizedThreadStart(object obj)

// 创建一个新线程的尝试:

new Thread(delegate ()          {  //..});

new Thread(delegate (object o)  {  //..});

new Thread(delegate             {  //..});

// 编译器将不知道第三行delegate省却的形参到底是哪个委托,因为它既可能是ThreadStart,又可以是ParameterizedThreadStart。

1.2  订阅的容器 event

  首先,在此需要认同一个观点:

  属性不是字段——很多时候,属性是字段的包装器,保护字段不被滥用。而包装器永远不可能是包装的东西。

  知道如何写封装的方法后,接下来便是——如何去打包这些方法。即:如何把这些方法添加(或者说是整合)到某个对象上。这种“添加”,一般需要一个“盒子”,它的关键字名称叫作事件(event)。

  把方法装进事件当中,C#规定了这两个符号,

  ◆ += 表示“订阅”,-= 表示“退订”;

  ◆ 实例化后,该实例的事件成员只能出现在 += 或 -= 符号的左边。

  ◆ 只要订阅了,事件一旦执行,所有订阅的方法都会执行。

  姑且可以把事件当成一个方法集合(+= 看做Add, -= 看做Remove)。

  声明格式见下(关键字  delegate类型  事件变量名称  =  delegate {..}):

public event EventHandler click = delegate {};

 ( * 上行省却的方法参数,编译器将参考”方法规则” )

  以上声明方法是赋值式的,即会替换掉该事件当前订阅的所有内容,此处要注意。

  示例:

    class Program
{
static void Main(string[] args)
{
Test a = new Test();
a.TestEvent += delegate() { Console.WriteLine("First Action."); };
a.TestEvent += SecondAction;
a.TestEvent += () => { Console.WriteLine("Third Action."); };
a.TestAction();
Console.WriteLine("================");
a.TestEvent -= SecondAction;
a.TestAction();
} public static void SecondAction()
{
Console.WriteLine("Second Action.");
}
} class Test
{
public event Action TestEvent;
public void TestAction()
{
if (TestEvent != null)
TestEvent();
}
}

  这个例子是不是非常眼熟,和控件的事件订阅是一样的。

  比如CheckBox的勾选事件:

  _checkBox.Checked += _checkBox_Checked;
 // TIPS:输入+=后长按Tab键,IDE将自动生成方法;+=后按一次Tab,自动生成lambda表达式方法。

private void _checkBox_Checked(object sender, RoutedEventArgs e) { }

  同理鼠标点击事件、双击等等,只不过像是监听鼠标操作(点下左键、松开左键等等)的这一项交由C#来处理了。

  注意:如果多次初始化界面,同一变量再次订阅,将订阅多次哦。

==================================================================================

  下节预告:

  属性不是字段——很多时候,属性是字段的包装器,保护字段不被滥用。包装器永远不可能是包装的东西。

注释:

[1] 自《深入理解C#》(第3版)Jon Skeet 著  姚琪琳 译

[2] 自 刘猛铁的C#学习视频

【C#进阶】委托那些事儿(一)的更多相关文章

  1. 【C#进阶】委托那些事儿(二)

    二.传统的委托 接下来讲一讲方法参数.下面以“餐馆服务员为客户下单”[2]的事件作为描述.一般对事件的做法分3个部分: 1. 方法参数 EventArgs,一般用于传送数据.在本例场景中 public ...

  2. [.net 面向对象程序设计进阶] (5) Lamda表达式(一) 创建委托

    [.net 面向对象程序设计进阶] (5) Lamda表达式(一)  创建委托 本节导读: 通过学习Lambda表达式,学会创建委托和表达式目录树,深入了解Lambda的特性,让你的代码变的更加清晰. ...

  3. form表单那点事儿(下) 进阶篇

    form表单那点事儿(下) 进阶篇 上一篇主要温习了一下form表单的属性和表单元素,这一片主要讲解用JavaScript如何操作form. 目录: 表单操作 取值 赋值 重置 校验 提交 技巧 不提 ...

  4. JavaScript进阶系列06,事件委托

    在"JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件,事件参数"中已经有了一个跨浏览器的事件处理机制.现在需要使用这个 ...

  5. c#进阶之浅析委托和事件

    何为委托 加了delegate关键字,没有方法体{}的方法模版(方法列表);委托是一种类型 public void Write() { //TODO } //加上关键字delegate,去掉方法体{} ...

  6. js进阶---12-12、jquery事件委托怎么使用

    js进阶---12-12.jquery事件委托怎么使用 一.总结 一句话总结:通过on方法(事件委托),给要绑定事件的元素的祖先绑定事件,从而达到效果. 1.事件委托是什么? 通过事件冒泡,让子元素绑 ...

  7. .NET进阶篇-语言章-2-Delegate委托、Event事件

    知识只有经过整理才能形成技能 整个章节分布简介请查看第一篇 内容目录 一.概述 二.解析委托知识点 1.委托本质 2.委托的使用 3.委托意义 逻辑解耦,减少重复代码 代码封装支持扩展 匿名方法和La ...

  8. 【C#进阶】多播委托和委托数组像是一回事~

    这个MathOperation类有三静态方法,参数都是double,并且没有返回值,考虑用Action<>() 这种预定义的委托哦 class MathOperations { publi ...

  9. 4、C#进阶:MD5加密、进程、线程、GDI+、XML、委托

    MD5加密 将字符串进行加密,无法解密.网上的解密方式也都是在库里找,找不到也没有. 1 protected void Page_Load(object sender, EventArgs e) 2 ...

随机推荐

  1. Winform关于OpenFileDialog的使用方法

    1.OpenFileDialog控件有以下基本属性InitialDirectory 对话框的初始目录Filter 要在对话框中显示的文件筛选器,例如,"文本文件(*.txt)|*.txt|所 ...

  2. SQL日期和时间函数

    使用这些函数可以计算日期和时间值.例如,假设您希望了解通常在一周中哪一天的销售量最高.使用 DAYOFWEEK 函数,您可以创建一个公式来标识每天的销售订单数量.再比如,假设您希望比较在过去的一年中的 ...

  3. maven不存在jar包解决

    win7环境 下载:https://maven.apache.org/download.cgi 提取文件,并cmd 转到bin目录 假设要添加的jar包是jbarcode-0.2.8.jar, 可执行 ...

  4. session以及分布式服务器session共享

    一.session的本质 http协议是无状态的,即你连续访问某个网页100次和访问1次对服务器来说是没有区别对待的,因为它记不住你. 那么,在一些场合,确实需要服务器记住当前用户怎么办?比如用户登录 ...

  5. phpcms中调用外部网站数据

    1.在phpcms后台模块->模块管理->数据源->外部数据源 中 添加外部数据源 2.在phpcms前台模板中,使用get标签获取数据源中数据. {pc:get sql=" ...

  6. 轻松学SQL Server数据库

    轻松学SQL Server数据库pdf   下载地址:网盘下载 目录:  第1章 数据库与SQL Server 2008 11.1 数据库基础 21.1.1 数据库的概念 21.1.2 数据库模型 2 ...

  7. 20172325 2017-2018-2 《Java程序设计》第八周学习总结

    20172325 2017-2018-2 <Java程序设计>第八周学习总结 教材学习内容总结 1.关于绑定 绑定:在执行程序时产生一个请求事件,需要执行一段代码来来完成方法调用,即一个方 ...

  8. Linux 磁盘分区存放文件和目录的数量 (inode)

    文件系统格式centos7缺省是xfs,centos6缺省是ext4,centos5缺省是ext3ext3 文件数最大支持31998个,文件系统容量最大16TB,单个文件最大2TBext4 文件数最大 ...

  9. 让QQ好友现形

    方法一 现在使用QQ的朋友,越来越注重保护自己的个人信息,如果对方将个人资料设置为保密你就无法看到对方的资料了,而这位好友如果又有着不断变换昵称的不良习惯,那么随着QQ好友名单的不断增加,时间一长,你 ...

  10. 如何使用css来让图片居中不变形 微信小程序和web端适用

    图片变形很多人祭奠出了妖魔鬼怪般的各种大法,比如使用jq来写,或者使用css表达式来写.今天我总结的是使用css3来写,唯一最大缺点就是对一些浏览器版本不够兼容.下面就是关于如何使用css来让图片居中 ...