学习中迸发的小灵感在学习编程语言是冒泡排序是我们绕不开的一个课题在最开始我也只会写固定的int类型的排序。随着学习的不断深入接触到泛型后我便想着既然它能支持实现IComparable的类型那么便有实现冒泡排序的可能。普通类实现冒泡排序我们先来看一看普通类实现冒泡排序的方式如下using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace practice { internal class Program { static void Main(string[] args) { //创建一个数组 int[] array new int[] { 1, 3, 5, 77, 2, 12, 56, 34, 23, 11, 17, 13 }; //打印原数组 Console.Write(原数组); foreach (var n in array) { Console.Write({0} , n); } Console.WriteLine(); //创建一个bubbles 类对象 BubbleSorterA bubblesA new BubbleSorterA(); //调用ToSort方法 来实现冒泡排序 bubblesA.Sort(array); //打印冒泡排序后的数组 Console.Write(冒泡排序后的数组); foreach (var n in array) { Console.Write({0} ,n); } } } //创建一个类 public class BubbleSorterA { /// summary /// 创建一个方法以此来实现冒泡排序 /// /summary /// param namearray传入原数组以实现冒泡排序/param public void Sort(int[] array) { //当数组为空时 提醒用户 if(array null) { //代码提前拦截程序在这里终止方法执行并告诉用户错误的地方 throw new ArgumentNullException(nameof(array),待排序数组不能为null); } //数组元素小于2无需排序直接返回 if(array.Length 1) { return; } //第一层for循环是要进行多少次排序 for(int i 0;iarray.Length;i) { //利用bool值 作为有序标记 bool isSwap false; //第二层for循环 是数组内相邻元素进行比较大小 for(int j 1;jarray.Length-1-i;j) { //利用if语句来实现升序 if (array[j 1] array[j]) { int tmparray[j1]; array[j1]array[j]; array[j]tmp; //本轮发生交换时 isSwap true; } } //本轮没有发生任何交换时数组已经全部有序直接跳出循环 if(!isSwap) { break; } } } } }我通过创建了一个普通类BubbleSorterA通过调用Sort方法传入原数组的方法来实现的。我们可以看到这个实现方法支持的仅int[ ]一种类型若数组中误写入float或double类型的数字那么程序就会报错出现异常。运行结果如下这是最容易理解的实现但复用性差。泛型类实现冒泡排序这是用泛型类实现的冒泡排序using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace practice_02 { internal class Program { static void Main(string[] args) { //创建待排序的整型数组 int[] array { 45, 1, 34, 2, 15, 3, 21, 20, 11, 9, 6, 5 }; //打印原数组 Console.Write(原数组为); //循环输出原数组的所有元素 foreach (var t in array) { Console.Write({0} , t); } //创建冒泡排序器实例 BubbleSorterB bubblesB new BubbleSorterB(); //调用泛型排序方法 bubblesB.Sort(array); Console.WriteLine(); //打印排序完成的数组 Console.Write(排序后的数组为); //循环输出排序后的所有数组 foreach (var t in array) { Console.Write({0} ,t); } } } /// summary /// 冒泡排序工具类泛型实现 /// /summary public class BubbleSorterB { /// summary /// 泛型冒泡排序方法 /// /summary /// typeparam nameT数组元素类型必须实现IComparable接口支持大小比较/typeparam /// param namearray需要排序的数组/param public void SortT(T[] array) where T : IComparable { //当数组为空时 提醒用户 if(array null) throw new ArgumentNullException(nameof(array),待排序数组不能为null); //当数组长度小于等于1时无需排序直接退出 if (array.Length 1) return; //外层for循环 是指一共最多进行length-1轮冒泡 for (int i 0; i array.Length; i) { //设置bool值 作为有序标记 来判断本轮是否发生交换 bool isSwapped false; //内层循环每一轮把最大元素排到右侧 length-1-i 即后面i个元素已经排好序不用再比较 for (int j 0; j array.Length - 1 - i; j) { //array[j1].CompareTo(array[j]) 0 代表后一个元素 前一个元素 if (array[j 1].CompareTo(array[j]) 0) { //利用中间变量 交换两个元素 T tmp array[j 1]; array[j 1] array[j]; array[j] tmp; //当发生交换时标记为true isSwapped true; } } //若标记为false 即本轮没有任何交换数组已经全部有序直接跳出循环提前结束 if (!isSwapped) break; } } } }在此代码中我通过创建了泛型类BubbleSorterB并加入了where T :IComparable类型约束它能限定传入的类型T必须实现IComparable接口并保证它一定具备“比较大小”的能力where T : IComparable调用Sort方法并向其中传入原数组public void SortT(T[] array)在方法中调用CompareTo()方法来实现的此写法实现了IComparable接口支持C#所有基础类型。用同一套泛型方法来排序int数组 string数组例如static void Main(string[] args) { BubbleSorterB sorter new BubbleSorterB(); //1排序int数组 int[] intArray { 45, 1, 34, 2, 15, 3, 21 }; //用实现了字符串的拼接 //string.Join(分隔符,数组) 遍历数组同时把所有元素拼接成一个完整字符串元素之间使用指定分隔符隔开 Console.WriteLine(int数组排序前 string.Join(, , intArray)); sorter.Sort(intArray); Console.WriteLine(int数组排序后 string.Join(, , intArray)); Console.WriteLine(); //2排序string数组 string[] strArray { banana, apple, cherry, date, blueberry }; Console.WriteLine(string数组排序前 string.Join(, , strArray)); sorter.Sort(strArray); Console.WriteLine(string数组排序后 string.Join(, , strArray)); }运行结果如下它们之间的优缺点对比维度普通类固定 int 类型实现泛型类实现支持类型仅支持int[]一种类型支持所有实现IComparable的类型int/double/string/ 自定义类等代码复用性极差新增类型必须重写整套排序逻辑极强一套代码适配所有可比较类型学习门槛极低只需要懂循环、类和方法中等需理解泛型、类型约束、IComparable 接口性能表现理论最优零额外开销首次调用有极微的泛型初始化开销后续运行几乎无差异类型安全编译时强类型安全编译时强类型安全无装箱拆箱扩展性差新增排序规则、新类型都要改核心代码强可轻松扩展自定义比较器、降序排序适用场景算法学习、作业演示、单一固定类型排序工业级开发、通用工具类、多类型排序场景我们通过这个表格可以知道普通类的优点是1.代码极度直观对刚入门的比较友好2.报错直白调试简单出现的问题几乎都是算法逻辑错误局限性同样也很明显它的复用性几乎为零不符合开闭原则反观泛型类它的优点有1.一套代码全类型复用2.编译时类型安全3.开闭原则友好局限性也是有的它有一定学习门槛如果你是初学算法、做简单作业用普通类实现专注算法本身。如果你要写通用工具类、做项目开发必须用泛型实现保证可维护性和扩展性。如果你需要极致性能且只有单一类型可以用固定类型实现。学习感悟初学冒泡排序时我先用普通类完成了仅支持 int 数组的实现。虽然我写的这个版本语法简单但它帮我吃透双层循环、元素交换与有序标记优化顺利理解了冒泡排序核心原理虽然只能处理单一类型复用性很差但也确实是我的来时路。接触泛型后我开始重写冒泡排序。一开始很难理解类型约束where T : IComparable和CompareTo通过在网上查找资料慢慢弄懂后才豁然开朗。同一套代码既能排序 int 数组也能排序string 数组不用重复编写算法逻辑真切感受到泛型消除代码冗余、提高复用性的优势。这次实践让我体会到编程的进阶之路先实现功能再追求通用。基础写法用来理解算法泛型方案贴近实际开发。今后写代码不能只满足于 “跑通就行”要多思考如何优化、提升代码可复用性。最后这句话不仅写给你们也勉励我自己。不急于求成持续优化代码也持续优化自己。