匿名委托的学习

什么是委托?MSDN上面是这样解释的

委托是一种定义方法签名的类型,可以与具有兼容签名的任何方法关联。您可以通过委托调用方法。委托用于将方法作为参数传递给其他方法。

那我们为什么要了解委托呢,不知道委托行不行吖?答案是不行的,委托是在.net中很基础的东西,包括事件是都是委托。

委托具有以下特点:

  • 委托类似于 C++ 函数指针,但它们是类型安全的。
  • 委托允许将方法作为参数进行传递。
  • 委托可用于定义回调方法。
  • 委托可以链接在一起;例如,可以对一个事件调用多个方法。
  • 方法不必与委托签名完全匹配。有关更多信息,请参见Covariance and Contravariance委托中的协变和逆变(C# 编程指南)
  • C# 2.0 版引入了匿名方法的概念,此类方法允许将代码块作为参数传递,以代替单独定义的方法。C# 3.0 引入了 Lambda 表达式,利用它们可以更简练地编写内联代码块。匿名方法和 Lambda 表达式(在某些上下文中)都可编译为委托类型。这些功能统称为匿名函数。

那我们学习委托能给我们带来什么好处捏?

我想好处大概有以下:

1.当然提高效率了,以前要写N个函数的地方,现在一个委托就搞定了。说白了,就是如何偷懒。

2.安全性得到了提高,都交给委托去办了,我们就不用担心了,当然这是在非常了解委托的前提下 。

在园子还有一篇关于委托的文章这里也有,文章讲了很多,,基本上从重构开始到模式,将委托和事件的思维过程完全重现,文中是一步步来思考,一步步解释委托,、由思考过程来导向,一番看下来,简直是享受啊,强烈建议新手看看,不要去MSDN上面死板的说明,强力推荐。

下面的代码来记录我学习委托的过程。

using System;

using System.Collections.Generic;

using System.Text;

namespace Artur.Study.MyDelegate
{
//好我们先定义一个委托,注意:
//该委托有一个string类型的形参跟方法SampleDelegateMethod签名一样
//何为方法的签名?
//方法的签名在声明该方法的类中必须唯一。

//方法的签名由方法的名称及其参数的数目、修饰符和类型组成。方法的签名不包含返回类型。
//见这里C# 语言规范 3.0 1.6.6节

//在方法重载的上下文中,方法的签名不包括返回值。但在委托的上下文中,签名的确包括返回值。换句话说,方法和委托必须具有相同的返回值。 见MSDN

delegate void SampleDelegate(string name);
class MyDelegateSample
{
staticvoid SampleDelegateMethod(string name)
{
Console.WriteLine(name);
}
staticvoid mysd(string mes)
{
Console.WriteLine(mes+”,the second time”);
}
staticvoid Main()
{
string myde=”Artur”;
//声明一个带参数的委托先

SampleDelegate sd1 = SampleDelegateMethod;
//注意等号的右边可以直接是函数名,这样最简便
//也可以是这样的,将函数名当做参数传递
//SampleDelegate s = new SampleDelegate(SampleDelegateMethod);
//再声明一个匿名委托,

SampleDelegate sd2 =delegate(string message)
{
Console.WriteLine(message);
Console.WriteLine(myde);
//匿名函数在这里访问了当前上下文的变量myde,该变量并不在函数方法内部。

};
//匿名委托不用以函数名为参数进行传递了,直接具体的实现函数

//可以将多个方法绑定到同一个委托变量,如下:

SampleDelegate mysd1;

mysd1 = SampleDelegateMethod;
mysd1 += mysd;

mysd1(“Hello World”);

//该委托会依次调用绑定的方法

Console.ReadLine();
}

}

}

hello World

this is a anonymous delegate

Artur
Hello World

Hello World,the second times

还有个例子在VS2008的QuickStart文件夹下面的。

using System;
using System.Collections.Generic;
using System.Text;

namespace AnonymousDelegate_Sample
{

//委托的定义必须与最终被调用的方法保持签名一致
//委托与最终调用的方法的签名必须一致

delegate decimal CalculateBonus(decimal sales);
//声明了一个委托的方法,返回类型为decimal,参数为decimal

//定义个一个类Enployee
class Employee
{
public string name;
public decimal sales;
public decimal bonus;
public CalculateBonus calculation_algorithm;
}

class Program
{

//定义了两种委托方法执行计算奖金
//一种是指定方法的委托,另一种是匿名委托

/*下面是第一个委托所指定的方法
* 声明了一个计算可执行的奖金算法
*/
static decimal CalculateStandardBonus(decimal sales) //静态的方法 签名跟委托一样的
{
return sales / 10;
}

static void Main(string[] args)
{

decimal multiplier = 2;
/*是声明一个在算法中用到的变量
* 该变量会被匿名委托访问
*/

CalculateBonus standard_bonus = new CalculateBonus(CalculateStandardBonus);
//定义个一个委托,将函数CalculateStandardBonus当做参数进行传递

CalculateBonus enhanced_bonus = delegate(decimal sales) { return multiplier * sales / 10; };
//再次定义一个委托,注意这里是匿名的委托,没有指定函数名,但是编译器怎么知道是函数CalculateStandardBonus呢
//答案是唯一的签名,返回类型和参数类型都为decimal只有函数CalculateStandardBonus()
// 实例化一些员工对象
Employee[] staff = new Employee[5];

for (int i = 0; i < 5; i++)
staff[i] = new Employee();

// 实例化赋值 Employees.
staff[0].name = “Mr Apple”;
staff[0].sales = 100;
staff[0].calculation_algorithm = standard_bonus;

staff[1].name = “Ms Banana”;
staff[1].sales = 200;
staff[1].calculation_algorithm = standard_bonus;

staff[2].name = “Mr Cherry”;
staff[2].sales = 300;
staff[2].calculation_algorithm = standard_bonus;
//上面的三个使用的是具体方法的委托
staff[3].name = “Mr Date”;
staff[3].sales = 100;
staff[3].calculation_algorithm = enhanced_bonus;

staff[4].name = “Ms Elderberry”;
staff[4].sales = 250;
staff[4].calculation_algorithm = enhanced_bonus;
//上面2个匿名委托

//为所有员工计算福利
foreach (Employee person in staff)
PerformBonusCalculation(person);

//显示全部员工的详细信息
foreach (Employee person in staff)
DisplayPersonDetails(person);

Console.Read();
}

public static void PerformBonusCalculation(Employee person)
{

//该方法利用委托存储person对象

//注意该方法可访问multiplier局部变量,尽管multiplier变量不在该方法内部
//即是具体的参数具体实现。
person.bonus = person.calculation_algorithm(person.sales);
}

public static void DisplayPersonDetails(Employee person)
{
Console.WriteLine(person.name);
Console.WriteLine(person.bonus);
Console.WriteLine(“—————“);
}

在这个QuickSatrt的例子,声明了两个委托来计算福利,一个是带具体方法名的委托,一个是匿名委托

总结:

1.委托实际上就是将函数当做传参数来传递

2.匿名委托与委托最大的区别就是能够访问当前上下文的变量,即使变量不在方法内部。

3.事件其实也是一种委托。

4.在委托中必须具有相同的方法签名,包括返回类型和参数。

发表评论

电子邮件地址不会被公开。 必填项已用*标注