很多小伙伴在学习了C#的泛型和委托后,很容易出现脑子里学会了,但手就是不听使唤,不知道怎么用,更不用说如何将两者结合起来使用。这次我就用经典实例冒泡排序结合泛型委托来介绍它们如何使用,理解了之后,相信小伙伴们对泛型和委托都有更加深刻的认识。
我们大多数情况使用冒泡排序都是为整形数据排序,排序的评判规则为比较两个它们的大小。但在现实世界,我们的评判规则可能会没有像比较数字的大小那么简单,我们有可能会比较两个人谁更优秀,这两件衣服哪个更适合我等等。也就是说我们要排序的数据,它的类型不确定,它的评判规则不确定。明确了这个问题,我们就能够想到使用泛型和委托来解决了。泛型可以解决类型不确定的问题,委托可以解决评判规则不确定的问题。具体怎么解决呢,活不多说,直接上代码
public static void Sort<T>(T[] data,Func<T,T,bool> condition,Action<T,T> action)
{
for (int i = 0; i < data.Length; i++)
{
bool isSort = false;
for (int j = data.Length-1; j >i; j--)
{
if (condition(data[j],data[j-1]))
{
isSort = true;
action(data[j], data[j - 1]);
T temp = data[j];
data[j] = data[j - 1];
data[j - 1] = temp;
}
}
if (!isSort)
break;
}
}
这个冒泡排序方法,第一个参数为要排序的数组,第二个参数为评判规则,第三个参数为每次被调换位置时,它有什么行为,根据需要可有可无。
它有多么神奇和美妙呢,我们使用一下就知道了
首先简单的定义一个学生类
public class Student
{
public string name;//姓名
public int age;//年龄
public int MathScore;//数学成绩
public int EnglishScore;//英语成绩
public int sortNum;//排序过程中被调换位置的次数
public Student(string name, int age, int mathScore, int englishScore)
{
this.name = name;
this.age = age;
MathScore = mathScore;
EnglishScore = englishScore;
}
public override string ToString()
{
return $"姓名:{name} 年龄:{age} 数学{MathScore} 英语{EnglishScore} 总分{MathScore+EnglishScore}";
}
}
接着就在main方法中使用吧
先实例化学生数组,每个学生数据用的随机数生成
static void Main(string[] args)
{
Student[] students = new Student[10];
Random random = new Random((int)DateTime.Now.Ticks);
for (int i = 0; i < 10; i++)
{
Student s = new Student("张三" + i, random.Next(10, 30), random.Next(60, 90), random.Next(60, 90));
students[i] = s;
Console.WriteLine(s);
}
Console.WriteLine("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
}
输出结果为
然后就请出今天的主角,开始排序吧
在这之前先确定两点,排序类型为Student类型,评判规则为年龄大小
根据这个定义两个方法,作为冒泡排序的参数使用
static bool Equals(Student stu1, Student stu2)
{
return stu1.age < stu2.age;
}
static void SortCall(Student stu1, Student stu2)
{
stu1.sortNum++;
stu2.sortNum++;
}
然后接着在main方法中写
Sort<Student>(students, Equals, SortCall);
for (int i = 0; i < 10; i++)
{
Console.Write(students[i]);
Console.WriteLine(" 我的位置总共换了" + students[i].sortNum + "次");
}
Console.WriteLine("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
输出结果为
学生们正确的根据年龄大小排序了,怎么样,是不是感觉很方便,我可以只用这一个方法就能随便对某个类型的集合进行排序了,还能自己决定它们两个谁更厉害,想想就刺激。
别急,配合Lamda表达式更加方便哦
在main中调用
Sort<Student>(students, (s1, s2) => { return s1.MathScore>s2.MathScore; }, (s1, s2) => {
//TODO
//自定义行为
});
输出结果就不发了,根据代码也能看出来这次要根据数学成绩从大到小排列了。
总之,泛型委托使用得当能极大的提高代码的复用以及扩展性,这么强的特点你确定要放弃吗?