以下均是个人拙见,如果有错误的地方,请大家及时指出,还有代码是在记事本里面敲得,编译可能不会通过,请见谅
对于C#入门者来说,接触的最多的恐怕就是事件了,但现在我们不讲事件,我们就看看委托给我们带来的好处
假设有一个类
class Student
{
//这里为了简便就不用属性了
public int id;
public string name;
public int age;
public int classId;//假设有一个班级编号
public Student(int id,string name,int age,int classId)
{
//...
}
}
class program
{
static void main(String[] args)
{
//声明一个Student的数组,这里大家不要钻牛角尖,
//为什么不用List或者List<T>呢,因为二者都是微软封装好的数据结构,实现了排序,没必要我画蛇添足
Student[] s={
new Student(1004,"成成",19,4),
new Student(1002,"张才",22,1),
new Student(1003,"李大为",20,4),
new Student(1005,"冰冰",23,5)
new Student(1001,"李晓红",21,3),
}
//排序
Sort(s);//完成排序
}
//实现冒泡排序法
private void Sort(student[] s)
{
for (int i = 0; i < s.Length -1; i++)//控制轮数
{
for (int j = 0; j < s.Length - 1 - i; j++)//控制交换次数
{
if s[j].id > s[j + 1].id)
{
Student temp = S[j];
s[j] = s[j + 1];
s[j + 1] = temp;
}
}
}
}
}
上面我们通过一个简单的方法实现了根据学号进行排序,该方法无返回值,接收一个Student型的数组,现在满足了命题,没有丝毫的问题。
可新问题来了,我们希望不仅可以通过学生的编号(id)也可以通过学生的年龄(age)进行排序,最容易想到的办法就是用Switch..Case
private void Sort(student[] s,sting sortfield)
{
Switch(sortfield)
case "id":
for (int i = 0; i < s.Length -1; i++)//控制轮数
{
for (int j = 0; j < s.Length - 1 - i; j++)//控制交换次数
{
if s[j].id > s[j + 1].id)//***********************************
{
Student temp = S[j];
s[j] = s[j + 1];
s[j + 1] = temp;
}
}
}
break;
case "age":
for (int i = 0; i < s.Length -1; i++)//控制轮数
{
for (int j = 0; j < s.Length - 1 - i; j++)//控制交换次数
{
if (s[j].age> s[j + 1].age)//******************************
{
Student temp = S[j];
s[j] = s[j + 1];
s[j + 1] = temp;
}
}
}
break;
}
现在调用的时候就变成
Sort(s,"id")或者Sort(s,"age")
大家注意我打星号的地方,我们是不是可以写出一个方法
//通过Student对象的id进行排序
private bool CompareById(Student s1,Student s2)
{
return s1.id>s2.id;
}
private bool CompareByAge(Student s1,Student s2)
{
return s1.Age>s2.Age;
}
于是Sort方法变成
private void Sort(student[] s,sting sortfield)
{
Switch(sortfield)
case "id":
for (int i = 0; i < s.Length -1; i++)//控制轮数
{
for (int j = 0; j < s.Length - 1 - i; j++)//控制交换次数
{
if (CompareById(s[j],s[j+1]))//***********************************
{
Student temp = S[j];
s[j] = s[j + 1];
s[j + 1] = temp;
}
}
}
break;
case "age":
for (int i = 0; i < s.Length -1; i++)//控制轮数
{
for (int j = 0; j < s.Length - 1 - i; j++)//控制交换次数
{
if (CompareByAge(s[j],s[j+1]))//******************************
{
Student temp = S[j];
s[j] = s[j + 1];
s[j + 1] = temp;
}
}
}
break;
}
新的问题又来了,我现在想通过班级号进行排序(当然比喻不一定恰当),最容易想到的办法就是借着加一个case,如果还有其他更多的要求,你将添加更多的case
这当然不利于程序的扩展,粘贴复制是不能适应不断变化的需求的,我们希望我们的方法变成
//实现冒泡排序法
private void Sort(student[] s)
{
for (int i = 0; i < s.Length -1; i++)//控制轮数
{
for (int j = 0; j < s.Length - 1 - i; j++)//控制交换次数
{
if (s[j].id > s[j + 1].id)//**************************CompareById(s[j],s[j+1]或者CompareByAge(s[j],s[j+1])
{
Student temp = S[j];
s[j] = s[j + 1];
s[j + 1] = temp;
}
}
}
}
大家注意我打星号的地方,我们现在在这里是不是可以任意传递比较的方法来实现排序,而无须无聊的复制,增加更多的case!
大家知道具有相同特征的东西都可以抽象出一个类,那方法可不可以抽象呢?如果方法可以抽象,我们只需要在打星号的地方写一个形参就可以了
CompareById和CompareByAge有什么相同的特征了,是的,除了方法名字不同,他们具有相同的返回值bool,也具有相同的输入参数,
在这个时候,委托因运而生,委托是什么呢?委托就是方法的一种抽象,就比如你我可以抽象成Person类,
CompareById和CompareByAge抽象后变成
public delegate bool CompareDelegate(Student s1,Student s2);
所以我们的Sort方法 变成
private void Sort(Student[] s,CompareDelegate method)
{
for (int i = 0; i < s.Length -1; i++)//控制轮数
{
for (int j = 0; j < s.Length - 1 - i; j++)//控制交换次数
{
if (method(s[j],s[j+1]))//调用
{
Student temp = S[j];
s[j] = s[j + 1];
s[j + 1] = temp;
}
}
}
}
所以现在的调用变成了
Sort(s,CompareById)或者Sort(s,CompareByAge);
如果你现在想根据班级排序,简单,写一个方法
private bool CompareByClassid(Student s1,Student s2)
{
return s1.classid>s2.classid;
}
然后调用变成Sort(s,CompareByClassid),可扩展性你也看到了
最后总结一下,委托是对方法的一种抽象
谢谢各位光顾我的博客,如果能留下你的脚印,我将不甚荣幸