一:背景资料
我们知道回调函数(callback)是WINDOWS编程的一个重要的部分。而回调函数实际是就是方法调用的指针,也成为函数指针。但在.NET中是不支持指针的,所以.NET就以委托的形式实现了函数指针的概念,而且这个委托是类型安全的。
我们知道,一个函数的参数不能是另外一个函数的,当将一个函数传递给另外一个函数的时候,就需要委托,将这个函数的指针传递过去。
二、问题来由
for (int j = i + 1; j < sortArray.Length; j++)
if (sortArray[i]<sortArray[j])
{
object temp = sortArray[i];
sortArray[i] = sortArray[j];
sortArray[j] = temp;
}
这个算法非常适合对int类型的排序,但是我们希望这个排序方法能够给任何对像进行排序。而且在代码运行前并不知道所比较的两个对象的类型,知道代码运行期间才知道是对什么类型对象的比较。那排序算法中的sortArray[i]<sortArray[j]的比较算法就有问题了。如何解决这个问题呢?答案是让客户机代码知道类在委托中传递的是什么方法,然后封装这个方法就可以进行比较了。
三、解决方案。
1、定义如下委托:
delegate bool CompareOp(object lhs, object rhs);
2、给Sort方法指定如下签名:
public static void Sort(object[] sortArray, CompareOp getCompareMethod)
3、设置完毕后,定义了如下类
{
/// <summary>
/// 冒泡排序方法
/// </summary>
/// <param name="sortArray">要排序的一组对象</param>
/// <param name="getCompareMethod">判断两个对象大小的方法</param>
public static void Sort(object[] sortArray, CompareOp getCompareMethod)
{
for (int i = 0; i < sortArray.Length; i++)
for (int j = i + 1; j < sortArray.Length; j++)
if (getCompareMethod(sortArray[i], sortArray[j]))
{
object temp = sortArray[i];
sortArray[i] = sortArray[j];
sortArray[j] = temp;
}
}
}
将比较两个对象大小的方法以委托的形式传递到排序方法中,就实现了一个冒泡排序针对所有类型的排序方法。
四、应用实例
我们定义一个Employee类来应用上面这个排序方法。如下:
{
private string _Name;
private decimal _Salary;
/// <summary>
/// 取得雇员的姓名
/// </summary>
public string Name
{
get { return _Name; }
set { _Name = value; }
}
/// <summary>
/// 取得雇员的工资
/// </summary>
public decimal Salary
{
get { return _Salary; }
set { _Salary = value; }
}
/// <summary>
/// 构造方法
/// </summary>
/// <param name="name"></param>
/// <param name="salary"></param>
public Employee(string name, decimal salary)
{
this._Salary = salary;
this._Name = name;
}
/// <summary>
/// 重写了tostring()方法
/// </summary>
/// <returns></returns>
public override string ToString()
{
return string.Format(_Name + ",{0:C}", _Salary);
}
/// <summary>
/// 比较两个对象的大小
/// </summary>
/// <param name="lhs"></param>
/// <param name="rhs"></param>
/// <returns></returns>
public static bool Compare(object lhs, object rhs)
{
Employee empLhs = (Employee)lhs;
Employee empRhs = (Employee)rhs;
return (empLhs._Salary > empRhs._Salary) ? true : false;
}
}
注意,比较两个对象大小的Compare方法的参数,是object,而不是Employee。这是为了匹配我们之前定义的委托的签名。也是为了实现一个公用化的排序方法。
客户机代码如下:
{
delegate bool CompareOp(object lhs, object rhs);
class MainEntryPoint
{
static void Main(string[] args)
{
Employee[] employees =
{
new Employee("Jone",2000),
new Employee("Tom",2500),
new Employee("Buddy",2300),
new Employee("Wiley",2800),
new Employee("Fudd",1900),
};
CompareOp compareOp = new CompareOp(Employee.Compare);
BubbleSorter.Sort(employees, compareOp);
for (int i = 0; i < employees.Length; i++)
Console.WriteLine(employees[i].ToString());
Console.ReadLine();
}
}
}
运行折行代码,就可以显示按照薪水排列的Employee。
五 总结
这是一个应用委托的一个简单的例子,但描述了如何使用委托来传递函数。委托其实就是一函数指针,我想,记住这一点是最重要的。