委托(Delegate)
回调函数callback是windows编程中的一个重要部分。回调实际上是方法调用的指针,也称为指针函数,是一个非常强大的编程特性。.NET以委托的形式实现了函数指针的概念,它的特殊之处在于,与函数指针不同,.NET的委托是类型安全的。这说明,C中的函数指针只不过是一个指向存储单元的指针,我们无法说出这个指针实际指向什么,像参数和返回类型等就更无从知晓了。
先来下面的代码:
Int I =int.Parse(“99”);
我们习惯于将数据作为参数传递给方法,所以,给方法传送另一个方法听起来就有点奇怪。有时候某方法执行的操作并不是针对数据进行的,而是要针对另一个方法进行操作。
在C#中定义委托
在C#中使用一个类时,分两个阶段。首先需要定义这个类,即告诉编译器这个类由什么字段和方法组成。然后(除非只使用静态方法)实例化类的一个对象。使用委托时,也需要经过这两个步骤。首先定义要使用的委托,对于委托,定义它就是告诉编译器这种类型的委托代表了哪种类型的方法,然后创建该委托的一个或多个实例。编译器在后台将创建表示该委托的一个类。
定义委托的语法如下:
delegatevoid IntMethodInvoker(int x);
在这个示例中,定义了一个委托IntMethodInvoker,并指定该委托的每个实例都包含一个方法的细节,该方法带有一个int参数,并返回void。理解委托的一个要点是它们的类型安全性非常高。在定义委托时,必须给出它所代表的方法签名和返回类型等全部细节。
所谓的方法签名,是只一个方法的返回类型及其参数列表的类型。
在C#中使用委托
给定委托的实例可以表示任何类型的任何对象上的实例方法或静态方法-- 只要方法的签名匹配于委托的签名即可。
下面的代码,将会介绍如何使用委托。
首先我们要编写一个类BubbleSorter,它执行一个静态方法Sort(),这个方法的第一个参数是一个对象数组,把该数组按照升序重新排列。换言之,假定传递的是int数组:{0, 5, 6, 2, 1},则返回的结果应是{0, 1, 2, 5, 6}。
class BubbleSorter
{
static public void Sort(object[] sortArray, Comparison comparison)
{
for (int i = 0; i < sortArray.Length; i++)
{
for (int j = i+1; j < sortArray.Length; j++)
{
if (comparison(sortArray[j], sortArray[i]))
{
object temp = sortArray[i];
sortArray[i] = sortArray[j];
sortArray[j] = temp;
}
}
}
}
}
delegate bool Comparison(object x, object y);
static public void Sort(object [] sortArray, Comparison comparison)
这个方法的文档说明强调,comparison必须表示一个静态方法,该方法带有两个参数,如果第二个参数的值"大于"第一个参数(换言之,它应放在数组中靠后的位置),就返回true。
为了使用这个类,需要定义另一个类,建立要排序的数组。
class Employee
{
private string _name;
private decimal _salary;
public Employee(string name, decimal salary)
{
this._name = name;
this._salary = salary;
}
public override string ToString()
{
return string.Format("{0}, {1:C}", _name, _salary);
}
public static bool CompareSalary(object x, object y)
{
Employee employee1 = (Employee) x;
Employee employee2 = (Employee) y;
return (employee1._salary < employee2._salary);
}
}
然后再添加一些客户端的代码:
using System;
namespace DelegateTest01
{
internal delegate bool Comparison(object x, object y);
class Program
{
static void Main(string[] args)
{
Employee[] employees =
{
new Employee("Bugs Bunny", 20000),
new Employee("Elmer Fudd", 30000),
new Employee("Daffy Duck", 25000),
new Employee("Wiley Coyote", (decimal)1000000.37),
new Employee("Foghorn Leghorn", 23000),
new Employee("RoadRunner", 50000),
};
BubbleSorter.Sort(employees, Employee.CompareSalary);
foreach (var employee in employees)
{
Console.WriteLine(employee);
Console.ReadKey();
}
}
}
}