因为定义委托基本上是定义一个新类,所以可以在定义类的任何相同地方定义委托,也就是说,可以在另一个类的内部定义,也可以在任何类的外部定义,还可以在名称空间中把委托定义为顶层对象。根据定义的可见性,和委托的作用域,可以在委托的定义上应用任意常见的访问修饰符:public、private、protected等:

实际上,“定义一个委托”是指“定义一个新类”。委托实现为派生自基类System.MulticastDelegate的类,System.MulticastDelegate又派生自基Syetem.Delegate。c#编译器能识别这个类,会使用其委托语法,因此我们不需要了解这个类的具休执行情况。这是c#与基类共同合作,使编程更易完成的一个范例。

构造函数:

在C#中,委托在语法上总是接受一个参数的构造函数,这个参数就是委托引用的方法。这个方法必须匹配最初定义委托时的签名。给定委托的实例可以引用任何类型的任何对象的实例方法或静态方法---只要方法签名匹配于委托的签名即可。

private delegate string GetAString();

int x=40;

GetAstring firststringMethod = new GetAstring(x.Tostring);

GetAstring firststringMethod = x.Tostring;

注意:

  1.因为int.Tostring()是一个实例方法(不是静态方法),所以需要指定实例(x)和方法名来正确地初始化委托。(int x = 40;和声明对象差不多,只不过等号右边不是使用的new)

  2.调用上述方法名时输入形式不能为x.ToString()(不要输入圆括号),也不能把它传送给委托变量。输入圆括号代表调用一个方法。调用x.ToString()方法会返回一个不能赋予委托变量的字符串对象。只能把方法的地址赋予委托变量

通过委托调用方法:委托名字后面加圆括号的方式,圆括号中应包含调用该委托中的方法时使用的任何等效参数

firstStringMethod();

实际上,使用委托实例+圆括号的方式与调用委托类的Invoke()方法完全相同。因为firstStringMethod是委托类型的一个变量,所以C#编译器会用firstStringMethod.Invoke();代替firstStringMethod();

firstStringMethod.Invoke();

委托推断:

为了减少输入量,只要需要委托实例,就可以只传送地址的名称。这称为委托推断。

委托数组:

delegate double DoubleOp(double x);

Double0p[] operations =
{

//MultiplyByTwo为MathsOperations类中的一个静态方法(*2)
Math0perations.MultiplyByTwo,

//Square为MathsOperations类中的一个静态方法(平方)
Mathoperations.Square
};

该数组的每个元素都初始化为由MathsOperations类实现的不同操作。然后遍历这个数组,把每个操作应用到
\ 3个不同的值上。这说明了使用委托的一种方式——把方法组合到一个数组中来使用,这样就可以
在循环中调用不同的方法了。
这段代码的关键一行是把每个委托传递给PrOces跛mⅡsplayNmberO方法,例如

                                匿名方法:

到目前为止,要想使委托工作,方法必须己经存在(即委托是用它将调用的方法的相同签名定义的)。但还有另外一种使用委托的方式:即通过匿名方法。匿名方法是用作委托的参数的一段代码。用匿名方法定义委托的语法与前面的定义并没有区别。但在实例化委托时,就有区别了。下面是一个非常简单的控制台应用程序,它说明了如何使用匿名方法:
using system;
namespace Wrox.ProCSharp。Delegates
(
class Program
(
static void Main()

{string mid = ",  midd1e part,";
Func<string,string>anonDel = delegate(string param)
{
param += mid;
param += " and this Was added to the string.";
return param;
}
Console.WriteLine(anonDel ("start of string"));

}}}

Func<string,string>委托接受一个字符串参数,返回一个字符串。anonDel是这种委托类型的变
量。不是把方法名赋予这个变量,而是使用一段简单的代码:它前面是关键字de1egate,后面是一
个字符串参数:

使用匿名方法注意事项:

匿名方法的优点是减少了要编写的代码。不必定义仅由委托使用的方法。在为事件定义委托时,
这是非常显然的(本章后面探讨事件)。这有助于降低代码的复杂性,尤其是定义了好几个事件时,
代码会显得比较简单。使用匿名方法时,代码执行得不太快。编译器仍定义了一个方法,该方法只
有一个自动指定的名称,我们不需要知道这个名称。
在使用匿名方法时,必须遵循两条规则。在匿名方法中不能使用跳转语句oreak、goto或om血∞)
跳到该匿名方法的外部,反之亦然:匿名方法外部的跳转语旬不能跳到该匿名方法的内部。
在匿名方法内部不能访问不安全的代码。另外,也不能访问在匿名方法外部使用的ref和out
参数。但可以使用在匿名方法外部定义的其他变量。
如果需要用匿名方法多次编写同一个功能,就不要使用匿名方法。在本示例中,除了复制代码,
编写一个指定的方法比较好,因为该方法只需编写一次,以后可通过名称引用它。
从C#3.0开始,可以使用Lambda表达式替代匿名方法。

                          Lambda表达式:

自C#3.0开始,就可以使用一种新语法把实现代码赋予委托:Lambda表达式,。只要有委托参数
类型的地方,就可以使用Lambda表达式。

using system;
namespace Wrox.ProCSharp。Delegates
(
class Program
(
static void Main()

{string mid = ",  midd1e part,";
Func<string,string>lambda= param =>
{
param += mid;
param += " and this Was added to the string.";
return param;
}
Console.WriteLine(anonDel ("start of string"));

}}}

Lambda运算符“=>”的左边列出了需要的参数。Lambda运算符的右边定义了赋予lambda变量的方法的实现代码。

Lambda的参数:

Lambda表达式有几种定义参数的方式。如果只有一个参数,只写出参数名就足够了。下面的Lambda表达式使用了参数s。因为委托类型定义了一个string参数,所以s的类型就是string。实现代码调用String.Format()方法来返回一个字符串,在调用该委托时,.就把字符串写到控制台上:
Func<string,string> oneParam = s => String.Format(
"change upperoase {0}", s.ToUpper());
Console.WriteLine(oneParam("test"));
如果委托使用多个参数,就把参数名放在花括号中。这里参数x和y的类型是double,由Func<double,double,double>委托定义:
Func<double, double, double> twoParams = (x,y) =) x * y;
Console.WriteLine(twoParams(3,2));
为了方便,可以在花括号中给变量名添加参数类型:
Func<doub△ e、 doub△ e、 doub△ e) tWoParamsWithTypes =
(double x, double y) => x * y;
Console.WriteLine(twoParamsWithTypes(4, 2));

如果Lambda表达式只有一条语句,在方法块内就不需要花括号和reum语句,因为编译器会添加
一条隐式的mum语句。但是,如果在Lambda表达式的实现代码中需要多条语句,就必须添加花括号和return语句:

在事件(观察者模式)中,对于订阅者(观察者),只需要提供提供一个方法即可,但是该方法的参数必须是两个,我们可以在该函数中,通过传过来的参数或许我们想知道的事情,或者通知的方式。然后把这个方法注册给事件就算完事儿了。这里还有一个约定俗称的规定,就是订阅事件的方法的命名,通常为“On事件名”,比如这里的OnNumberChanged。

c#高级编程笔记----委托的更多相关文章

  1. Android高级编程笔记(四)深入探讨Activity(转)

    在应用程序中至少包含一个用来处理应用程序的主UI功能的主界面屏幕.这个主界面一般由多个Fragment组成,并由一组次要Activity支持.要在屏幕之间切换,就必须要启动一个新的Activity.一 ...

  2. C#高级编程笔记 (6至10章节)运算符/委托/字符/正则/集合

    数学的复习,4^-2即是1/4/4的意思, 4^2是1*2*2的意思,而10^-2为0.01! 7.2运算符 符号 说明 例   ++ 操作数加1 int i=3; j=i++; 运算后i的值为4,j ...

  3. UNIX环境高级编程笔记之文件I/O

    一.总结 在写之前,先唠几句,<UNIX环境高级编程>,简称APUE,这本书简直是本神书,像我这种小白,基本上每看完一章都是“哇”这种很吃惊的表情.其实大概三年前,那会大三,我就买了这本书 ...

  4. javascript高级编程笔记01(基本概念)

    1.在html中使用JavaScript 1.  <script> 元素 <script>定义了下列6个属性: async:可选,异步下载外部脚本文件. charset:可选, ...

  5. C#高级编程笔记之第三章:对象和类型

    类和结构的区别 类成员 匿名类型 结构 弱引用 部分类 Object类,其他类都从该类派生而来 扩展方法 3.2 类和结构 类与结构的区别是它们在内存中的存储方式.访问方式(类似存储在堆上的引用类型, ...

  6. C#高级编程笔记之第二章:核心C#

    变量的初始化和作用域 C#的预定义数据类型 流控制 枚举 名称空间 预处理命令 C#编程的推荐规则和约定 变量的初始化和作用域 初始化 C#有两个方法可以一确保变量在使用前进行了初始化: 变量是字段, ...

  7. C#高级编程笔记 Day 7, 2016年9月 19日 (泛型)

    1.协变和抗变 泛型接口的协变 如果泛型类型用 out  关键字标注,泛型接口就是协变的.这也意味着返回类型只能是 T. 接口IIndex 与类型T 是协变的,并从一个制度索引器中返回这个类型. pu ...

  8. UNIX环境高级编程笔记 目录

    每一章的重点会使用加粗字体 第一章:UNIX基础知识:UNIX体系结构:文件和目录:输入和输出:程序和进程:出错处理:信号:时间值:系统调用和库函数 第三章:文件I/O:文件描述符:文件操作函数:文件 ...

  9. C#高级编程笔记(11至16章)异步/托管/反射/异常

    11.1.2LINQ语句 LINQ查询表达式以from子句开始,以select或者group子句结束.在这两个子句之间可以跟零个或者多个from.let.where.join或者orderby子句. ...

随机推荐

  1. 深度学习:Sigmoid函数与损失函数求导

    1.sigmoid函数 ​ sigmoid函数,也就是s型曲线函数,如下: 函数: 导数: ​ 上面是我们常见的形式,虽然知道这样的形式,也知道计算流程,不够感觉并不太直观,下面来分析一下. 1.1 ...

  2. Struts2报错:No result defined for action xxx and result input

    case如下: 1. 后台程序要升级, 修改了一些功能,但是没有修改或者添加action的参数. 2. 数据库需要升级,执行了一些sql,修改过action的值. 3. 当修改某个已经存在的记录,然后 ...

  3. 读《MySql必知必会》笔记

    MySql必知必会 2017-12-21 意义:记录个人不注意的,或不明确的,或不知道的细节方法技巧,此书250页 登陆: mysql -u root-p -h myserver -P 9999 SH ...

  4. hibernate框架的搭建与简单实现增删改

    Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自 ...

  5. 设计模式(一)单例模式:实现 Serializable 接口之后的额外操作

    思想: 一个单例类,无论采取哪一种设计(单元素枚举类除外), 一旦间接或者直接实现 Serializable 接口,为了保证单例,就要多增加一点考虑:保证类在反序列化之后能够保证单例. public ...

  6. HDU-1534 Schedule Problem

    四种约束条件..照做就行了.. 最长路建图. #include <cstdio> #include <cstdlib> #include <cstring> #in ...

  7. BZOJ-1798 维护序列

    线段树.支持区间加.区间乘.区间查询和. 标记下移还有取模要注意. var n,p,q,i,s,t:longint; a:int64; num,n1,n2,n3:array[0..500000] of ...

  8. Nginx合并静态资源,以减轻web服务器压力

    Nginx concat模块由淘宝开发,并且淘宝已经在使用这个Nginx模块.这个模块类似于apache中的modconcat.如果需要使用它,需要使用两个?问号.Nginx concat通过合并静态 ...

  9. UVa1476 Error Curves

    画出函数图像后,发现是一个类似V字型的图. 可以用三分法找图像最低点 WA了一串,之后发现是读入优化迷之被卡. /*by SilverN*/ #include<iostream> #inc ...

  10. 【CF1023C】Bracket Subsequence(模拟)

    题意:给定一个正则括号序列 s ,让你在当中选择一个长度正好为 t 的子串,使得 t 恰好也是一个正则括号序列 思路:用栈模拟 #include<cstdio> #include<c ...