一、 什么是委托:
大家先看一个示例:
下面类中是两个函数,分别实现的二倍,和平方的功能
class MathsOperations
{
public static double MultiplyByTwo(double value)
{
return value*2;
}
public static double Square(double value)
{
return value*value;
}
}
在下面代码中,我们需要多次调用这两个函数(大家想以一下按以前的方法调用我们应该如何写代码)
using System;
namespace SimpleDelegate
{
delegate double DoubleOp(double x);
class MainEntryPoint
{
static void Main()
{
DoubleOp [] operations =
{
new DoubleOp(MathsOperations.MultiplyByTwo),
new DoubleOp(MathsOperations.Square)
};
for (int i=0 ; i<operations.Length ; i++)
{
Console.WriteLine(“Using operations[{0}]:”, i);
ProcessAndDisplayNumber(operations[i], 2.0);
ProcessAndDisplayNumber(operations[i], 7.94);
ProcessAndDisplayNumber(operations[i], 1.414);
Console.WriteLine();
}
}
static void ProcessAndDisplayNumber(DoubleOp action, double value)
{
double result = action(value);
Console.WriteLine(
“Value is {0}, result of operation is {1}”, value, result);
}
下面是一个冒泡排序的函数
//void Boble(int[] sortArray) 可能不一定传入整型
for (int i = 0; i < sortArray.Length; i++)
{
for (int j = i + 1; j < sortArray.Length; j++)
{
if (sortArray[j] < sortArray[i]) // 比较的如果是自定义类型又如何?
{
int temp = sortArray[i]; // 交换的类型如果是其它类型?
sortArray[i] = sortArray[j];
sortArray[j] = temp;
}
}
}
看下面的代码,可以对所有类型的数据进行排序
class BubbleSorter
{
static public void Sort(object [] sortArray, CompareOp gtMethod)
{
for (int i=0 ; i<sortArray.Length ; i++)
{
for (int j=i+1 ; j<sortArray.Length ; j++)
{
if (gtMethod(sortArray[j], sortArray[i]))
{
object temp = sortArray[i];
sortArray[i] = sortArray[j];
sortArray[j] = temp;
}
}
}
}
}
定义自定义的类,完成员工按工资进行排序
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(name + “, {0:C}”, salary);
}
public static bool RhsIsGreater(object lhs, object rhs)
{
Employee empLhs = (Employee) lhs;
Employee empRhs = (Employee) rhs;
return (empRhs.salary > empLhs.salary) ? true : false;
}
}
using System;
namespace Wrox.ProCSharp.AdvancedCSharp
{
delegate bool CompareOp(object lhs, object rhs);
class MainEntryPoint
{
static void Main()
{
Employee [] employees =
{
new Employee(“Bugs Bunny”, 20000),
new Employee(“Elmer Fudd”, 10000),
new Employee(“Daffy Duck”, 25000),
new Employee(“Wiley Coyote”, (decimal)1000000.38),
new Employee(“Foghorn Leghorn”, 23000),
new Employee(“RoadRunner’”, 50000)};
CompareOp employeeCompareOp = new CompareOp(Employee.RhsIsGreater);
BubbleSorter.Sort(employees, employeeCompareOp);
for (int i=0 ; i<employees.Length ; i++)
Console.WriteLine(employees[i].ToString());
}
}
如果我们要排序的产品的大小(以库存或价格排序),又如何实现
关于对象排序,还有没有其它方法
可能的答案:重载比较操作符
必须成对重载
public static bool operator == (Employee e1, Employee e2)
{
if (e1.salary==e2.salary)
return true;
else
return false;
}
public static bool operator != (Employee e1, Employee e2)
{
if (e1.salary!=e2.salary)
return true;
else
return false;
}
public static bool operator < (Employee e1, Employee e2)
{
if (e1.salary<e2.salary)
return true;
else
return false;
}
public static bool operator > (Employee e1, Employee e2)
{
if (e1.salary>e2.salary)
return true;
else
return false;
}
小结:
委托是对相同参数和返回值的函数,可以交给一个对象支统一调用,可以重用代码
二、 多次委托:
DoubleOp operations = new DoubleOp(MathOperations.MultiplyByTwo);
operations += new DoubleOp(MathOperations.Square);
DoubleOp operation1 = new DoubleOp(MathOperations.MultiplyByTwo);
DoubleOp operation2 = new DoubleOp(MathOperations.Square);
DoubleOp operations = operation1 + operation2;
执行:Operations(3)
结果是什么?
分别调用了二倍和平方算法
小结:这样可以多次给委托对象赋值,然后一次输出
三、 事件
C#中的事件机制是通过委托来实现的
我们看一个例子:以上面的员工类为例
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(name + “, {0:C}”, salary);
}
public void save()
{
//code1
Console.WriteLine(name+”is saved”);
}
}
当我们希望在保存前能提示用户输入的信息时我们怎么做,我们在code1处加上一段代码
Console.WriteLine(“now is Saving data!,please wait”);
这样虽然可以,但这个类编译以后,代码就定死了不好改动了,如能在客户端给出回调代码则是较好的设计。
Using System;
Public delegate void EventHandle(); //1
class Employee
{
//略
public event EventHandle beforeSave; //2
public void save()
{
//code1
if(beforeSave!=null)
beforeSave(); //4
Console.WriteLine(name+”is saved”);
}
}
class Demo
{
public static void Main()
{
Employee emp = new Employee(“”,”ddd”);
Emp.beforeSave+=new EventHandle(MyBeforeSave); //5
Emp.save();
}
static void MyBeforeSave() //6
{
Console.WriteLine(“now is Saving.wait please”);
}
}
事件:
1. 定义一个公共委托方法Public delegate void EventHandle();
2. 在组件中用委托声明事件public event EventHandle beforeSave;
3. 增加事件注册和移除的方法 //可不用
4. 在要调用的方法前后加上委托的方法调用public void save()
5. 在客户端注册事件Emp.beforeSave+=new EventHandle(MyBeforeSave);
6. 在客户端写被委托的方法内容static void MyBeforeSave()
客户工程代码如下:
using System;
using System.Collections.Generic;
using System.Text;
namespace DelegateDemo
{
class Program
{
public static void Main()
{
Employee emp = new Employee("gobn",new Decimal(123.34));
emp.beforeSave+=new EnventHandle(MyBeforeSave); //5
emp.save();
Console.ReadLine();
}
static void MyBeforeSave() //6
{
Console.WriteLine("now is Saving.wait please");
}
}
}
Employee类如下
using System;
using System.Collections.Generic;
using System.Text;
namespace DelegateDemo
{
public delegate void EnventHandle();
class Employee
{
private string name;
private decimal salary;
public Employee(string name, decimal salary)
{
this.name = name;
this.salary = salary;
}
public event EnventHandle beforeSave; //2
public void save()
{
//code1
if(beforeSave!=null)
beforeSave(); //4
Console.WriteLine(name+" is saved");
}
}
}