html动漫网站模板下载,成都住建局官网房源,吴江网络推广,怎样才能注册一个公司思维导图总结不知不觉在Csharp的学习已经投入快1个月了#xff0c;这1个月下来学习的东西还是挺多的#xff0c;前面也分享了两篇博客#xff0c;这是我的第三篇博客了#xff0c;这周学习了很多东西#xff0c;主要学习了集合框架、字典、泛型等等#xff0c;所以一周一…思维导图总结不知不觉在Csharp的学习已经投入快1个月了这1个月下来学习的东西还是挺多的前面也分享了两篇博客这是我的第三篇博客了这周学习了很多东西主要学习了集合框架、字典、泛型等等所以一周一总结还是挺重要的这是我做的一个思维导图也是对这些知识点的大体的一个汇总如图所示下面我将为大家详细介绍一下这些内容一、常用类字符串类型stringstring是 C# 中用于表示字符序列的引用类型但其行为因不可变性和驻留性而具有特殊性。1. 核心特性不可变性字符串一旦创建其值无法修改。任何修改操作如拼接、替换都会创建新的字符串对象需注意频繁修改时的性能开销。驻留性相同字面量的字符串会被存储在 “驻留池” 中复用减少内存占用。代码示例string s1 hello; string s2 hello; Console.WriteLine(object.ReferenceEquals(s1, s2)); // True同一引用驻留规则仅编译期确定的字面量或通过string.Intern()手动添加的字符串会驻留运行时动态生成的字符串如拼接变量不会自动驻留。2. 常用操作1创建与属性直接赋值string str hello;构造函数支持字符数组或重复字符如new string(new[] {H,i})、new string(a, 5)5 个 a。关键属性Length获取长度[]索引器访问单个字符只读。2比较与判断相等比较默认比较值非引用string.Equals()支持指定比较规则如忽略大小写代码示例string str1 Hello; string str2 HELLO; Console.WriteLine(string.Equals(str1, str2, StringComparison.OrdinalIgnoreCase)); // True空值判断string.IsNullOrEmpty()判断是否为null或空字符串。string.IsNullOrWhiteSpace()判断是否为null、空字符串或仅含空白字符如空格。包含与匹配Contains()判断是否包含子串StartsWith()/EndsWith()判断首尾匹配。3拼接与格式化拼接方式运算符编译后等价于string.Concat()适合少量拼接。string.Join()连接数组 / 集合如string.Join(,, new[] {a,b})→a,b。字符串插值$简洁直观支持表达式和格式如$今天是{DateTime.Now:yyyy-MM-dd}。字面量忽略转义字符适合文件路径如D:\test.txt。格式化支持标准格式符如C货币、D十进制、yyyy-MM-dd日期例如代码示例Console.WriteLine(${123.45:C2}); // 123.45货币格式 Console.WriteLine(${DateTime.Now:HH:mm:ss}); // 23:59:59时间格式(4其他常用操作截取Substring(startIndex, length)如abcdef.Substring(2, 3)→cde。替换Replace(oldValue, newValue)替换所有匹配项。分割Split(分隔符)如a,b,c.Split(,)→ 字符串数组[a,b,c]。修剪Trim()移除首尾空白TrimStart()/TrimEnd()单独处理首尾。注意:1.这些方法全部记住显然不现实难免会忘记这很正常所以要多看多写多用2.如果有些方法实在不记得那也没关系但是你要学会自己使用帮助手册进行查询步骤1.打开我们的Visual Studio输入String鼠标停在上面按F1(有的电脑可能需要按FnF1),会跳转到我们C#的官方帮助手册2.跳转到该界面我们可以看到这个类的构造函数、方法、属性、字段等等3.点开方法我们就可以看到该类的方法你对哪一个方法不熟悉直接点进去就可以看到这个方法的具体作用、它里面的参数、返回值类型、注解等等所以我们要好好利用帮助手册忘记了就要学会去查。这里有一道常用类的面试题我们在常用类中经常会碰到就是null和“”它们是有区别的主要是在是否创建对象上面null是没有创建对象的是一个空引用而(空字符串)的话它是创建了对象的只是对象的内容为空。注意实际开发过程中都不推荐可变字符串StringBuilderStringBuilder位于System.Text命名空间专为频繁修改字符串场景设计避免因string不可变性导致的性能损耗。1. 核心优势可变性内部维护字符缓冲区修改操作拼接、插入等直接在缓冲区进行不会频繁创建新对象。容量管理默认容量 16不足时自动扩容翻倍建议初始化时指定合理容量如new StringBuilder(100)减少扩容次数。2. 常用操作构造支持初始字符串或容量如new StringBuilder(start)、new StringBuilder(200)。追加Append(value)添加内容支持多种类型AppendLine()追加后换行。插入 / 删除Insert(index, value)在指定位置插入Remove(startIndex, length)删除指定范围。转换通过ToString()转为string最终输出。代码示例var sb new StringBuilder(100); // 指定初始容量 sb.Append(Hello).Append( ).AppendLine(World); sb.Insert(5, ,); // 插入逗号 Console.WriteLine(sb.ToString()); // Hello, World日期时间类型DateTimeDateTime是结构体值类型用于表示具体的日期和时间位于System命名空间。1. 核心概念时间表示以 “Ticks” 为最小单位1 Tick 100 纳秒1 毫秒 10000 Ticks基准时间为公元 0001 年 1 月 1 日 00:00:00。时间种类通过Kind属性区分本地时间Local、UTC 时间Utc或未指定Unspecified。2. 常用操作1获取当前时间DateTime.Now本地当前时间含日期和时间。DateTime.UtcNowUTC 当前时间格林尼治时间。DateTime.Today本地当前日期时间部分为 00:00:00。2构造与属性构造支持年月日时分秒如new DateTime(2024, 10, 1, 8, 30, 0)。属性Year/Month/Day年月日、Hour/Minute/Second时分秒、DayOfWeek星期几等。示例DateTime dt new DateTime(2024, 10, 1); Console.WriteLine(${dt.Year}年{dt.Month}月是该年的第{dt.DayOfYear}天);3格式化输出通过ToString()或字符串插值指定格式常用格式符d短日期如2024/10/1。D长日期如2024年10月1日。t短时间如08:30。自定义格式yyyy-MM-dd HH:mm:ss如2024-10-01 08:30:00。四、数学运算类MathMath类位于System命名空间提供了一系列静态方法和常数用于执行基本数学运算如三角函数、对数、取整等无需实例化即可直接调用。1. 核心特性静态类所有方法和字段均为静态直接通过Math.方法名调用无需创建实例。跨平台一致性运算结果不依赖于系统环境确保不同平台下的计算一致性。支持基本类型主要针对double、int等数值类型部分方法支持decimal。2. 常用方法与常数1数学常数代码示例Console.WriteLine(Math.PI); // 3.141592653589793圆周率 Console.WriteLine(Math.E); // 2.718281828459045自然常数2基本运算绝对值Math.Abs(value)支持整数、浮点数等类型幂运算Math.Pow(base, exponent)返回double平方根Math.Sqrt(value)仅支持非负数向下取整Math.Floor(value)返回小于等于该值的最大整数向上取整Math.Ceiling(value)返回大于等于该值的最小整数四舍五入Math.Round(value)或指定小数位数Math.Round(value, digits)最大值 / 最小值Math.Max(a, b)、Math.Min(a, b)随机数生成类RandomRandom类位于System命名空间用于生成伪随机数基于种子的可预测序列适用于游戏、抽样、测试等场景。1. 核心作用生成伪随机数随机数序列由初始 “种子” 决定相同种子会生成相同序列。支持多种类型可生成整数、浮点数、字节数组等。2. 构造方法无参构造默认以系统时钟作为种子精度有限短时间内创建多个实例可能生成相同序列Random rnd new Random();指定种子手动传入整数种子用于复现随机序列如测试场景Random rnd new Random(123); // 固定种子每次运行生成相同序列3. 常用方法1生成整数随机数Next()返回非负随机整数0 ~int.MaxValue。Next(maxValue)返回小于maxValue的非负整数0 ~ maxValue-1。Next(minValue, maxValue)返回[minValue, maxValue)范围内的整数包含 min不包含 max。示例Random rnd new Random(); Console.WriteLine(rnd.Next()); // 例如123456 Console.WriteLine(rnd.Next(10)); // 0~9的随机数如5 Console.WriteLine(rnd.Next(1, 7)); // 1~6的随机数模拟骰子如32生成浮点数随机数NextDouble()返回[0.0, 1.0)范围内的随机双精度浮点数。示例Random rnd new Random(); double value rnd.NextDouble(); // 例如0.7321 // 扩展到指定范围如1.0~5.0 double scaled 1.0 rnd.NextDouble() * 4.0;3填充随机字节数组NextBytes(byte[] buffer)将字节数组填充为随机值每个元素 0~255。示例byte[] buffer new byte[4]; new Random().NextBytes(buffer); Console.WriteLine(BitConverter.ToString(buffer)); // 例如A3-7F-2C-1D4. 注意事项避免短时间创建多个实例系统时钟种子精度约 10-15 毫秒短时间内创建的Random实例可能共享同一种子导致随机数重复。建议全局共享一个实例// 推荐全局单例 private static readonly Random _globalRnd new Random();线程安全Random类不是线程安全的多线程环境下需加锁或使用线程本地实例ThreadLocalRandom。伪随机局限性不适用于加密场景如密码生成加密需使用System.Security.Cryptography.RNGCryptoServiceProvider生成真随机数。小结string适合静态字符串或少量修改场景注意不可变性和驻留机制对性能的影响。StringBuilder适合频繁拼接、修改字符串如循环中组装内容通过预指定容量优化性能。DateTime处理日期时间的核心类型注意本地时间与 UTC 时间的转换以及格式化输出的常用格式符。Math 类提供基础数学运算涵盖取整、幂运算、三角函数等无需实例化直接调用静态方法适合常规数值计算。Random 类生成伪随机数需注意种子特性和实例创建时机适用于非加密场景的随机数需求如游戏、抽样。掌握这些核心类的特性与用法能显著提升 C# 字符串处理和日期时间操作的效率与代码质量。二、List集合、队列、栈在 C# 开发中集合是存储和管理对象的核心工具。集合体系概览C# 的集合类型主要分为非泛型集合System.Collections命名空间和泛型集合System.Collections.Generic命名空间两大类核心类型如下集合类型非泛型System.Collections泛型System.Collections.Generic核心特性动态数组ArrayListListT可动态扩容的线性集合键值对集合HashtableDictionaryTKey, TValue基于键访问值的映射结构队列FIFOQueueQueueT先进先出的线性结构栈LIFOStackStackT后进先出的线性结构排序键值对SortedListSortedListTKey, TValue按键排序的键值对集合无重复元素集合-HashSetT不允许重复元素的集合双向链表-LinkedListT高效插入删除的链式结构ArrayList动态数组的早期实现核心特性本质底层基于object[]实现的动态数组支持自动扩容非类型安全所有元素均为object类型值类型存储需装箱读取需拆箱灵活性允许存储任意类型包括null支持重复元素可动态调整大小常用操作1.创建方式代码示例ArrayList list1 new ArrayList(); // 默认构造初始容量0首次添加扩容至4 ArrayList list2 new ArrayList(100); // 指定初始容量减少扩容次数 ArrayList list3 new ArrayList(new int[]{1,2,3}); // 从其他集合初始化2.核心方法添加Add()单个元素、AddRange()批量添加、Insert()指定索引插入删除Remove()按值删除首个匹配、RemoveAt()按索引删除、Clear()清空查找Contains()判断存在、IndexOf()正向查找索引、LastIndexOf()反向查找与数组的核心区别特性数组ArrayList类型安全强类型编译时检查非类型安全运行时可能抛类型转换异常大小特性固定长度创建后不可变动态大小自动扩容性能无装箱拆箱开销存在装箱拆箱性能较低功能丰富度仅基础操作需依赖 Array 类内置丰富方法增删改查、排序等注意现在实际开发过程不怎么用ArrayList这种非泛型的我们现在开发过程中用ListT这种泛型的集合比较多也比较安全功能更强大。ListT类型安全的泛型列表ListT是 ArrayList 的泛型改进版是现代 C# 开发的首选动态数组类型。与 ArrayList 的核心差异特性ArrayListListT类型安全存储object需强制转换编译时指定类型无需转换性能装箱拆箱开销大无装箱拆箱性能更优适用场景遗留代码、混合类型存储现代开发类型明确的集合常用操作创建与初始化代码示例Listint numbers new Listint(); // 空列表 Liststring names new Liststring{Alice, Bob}; // 初始化列表 Listdouble values new Listdouble(10); // 指定初始容量基础操作添加Add()、AddRange()访问通过索引器[index]读写删除Remove()、RemoveAt()、Clear()查找Contains()、IndexOf()高级功能排序内置排序元素实现IComparableT接口后调用Sort()自定义排序通过IComparerT接口或ComparisonT委托支持 Lambda代码示例// 示例按年龄降序排序 students.Sort((x, y) y.Age.CompareTo(x.Age));2.查找Find()查找首个符合条件的元素基于PredicateT委托FindAll()查找所有符合条件的元素示例// 查找第一个偶数 int even numbers.Find(n n % 2 0);3.转换:ConvertAllTOutput()转换为其他类型的列表ToArray()转换为数组List 高级用法精华作用告别繁琐、大量的循环简化我们的代码1、核心高级语法上周老师也讲过一道题题目是这样这个题目的话用List高级语法会更快代码量也跟少效率更高完整代码using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp1.work4 { /// summary /// 工人类 /// /summary internal class Worker { //属性 public int Age { get; set; } //年龄 public string Name { get; set; } //姓名 public Decimal Salary { get; set; } //薪水 //构造方法 public Worker(string name, int age, Decimal salary) { Name name; Age age; Salary salary; } //work方法 public void Work() { Console.WriteLine(${Name}正在工作...); } public override string ToString() { return ($姓名{Name} 年龄{Age} 薪水{Salary}); } } }2.核心优势无需手动写循环代码简洁易读基于 Predicate支持灵活的条件筛选类型安全避免装箱拆箱开销3.PredicateT与方法底层逻辑List 的高级方法Find/FindAll 等核心依赖PredicateT委托我们先拆解这个 “隐藏核心”再深入方法的细节Predicate1.定义public delegate bool Predicatein T(T obj);输入 T 类型参数返回 bool2.特性协变in 关键字允许传入派生类类型如Predicate可接收Predicate3.底层关联List 的高级方法本质是 “遍历集合 执行 Predicate 委托判断”简化手动循环的模板代码底层性能对比1.手动 for 循环 vs List.ForEach ()性能几乎一致ForEach () 底层也是 for 循环2.Find () vs 手动遍历Find () 代码更简洁但无性能优势均为 O (n)3.大数据量优化当 List 元素数 10 万时优先用HashSetT查找 O (1)替代 List或先 Sort () 再用 BinarySearch ()栈和队列栈Stack后进先出的数据结构栈遵循LIFOLast-In-First-Out原则适用于需 后进先出 处理的场景如表达式求值、调用栈模拟。核心特性仅允许从栈顶入栈Push、栈顶出栈Pop支持泛型StackT和非泛型Stack推荐使用泛型常用操作Stackint stack new Stackint(); stack.Push(1); // 入栈 stack.Push(2); int top stack.Pop(); // 出栈返回2栈中移除 int peek stack.Peek(); // 查看栈顶元素不删除返回1面试题这里也有1道面试题大家可以思考一下下一期公布答案有1个数组它里面的元素有1,3,6,5,8,9它的入栈顺序是1、3、6、5、8、9请问它的出栈顺序是什么有几种情况队列Queue先进先出的数据结构队列遵循FIFOFirst-In-First-Out原则适用于需按顺序处理的场景如任务队列、消息队列。核心特性仅允许从队尾入队Enqueue、队头出队Dequeue支持泛型QueueT和非泛型Queue推荐使用泛型类型安全常用操作Queuestring queue new Queuestring(); queue.Enqueue(任务1); // 入队 queue.Enqueue(任务2); string first queue.Dequeue(); // 出队返回任务1队列中移除 string peek queue.Peek(); // 查看队头元素不删除返回任务2 bool exists queue.Contains(任务2); // 判断是否存在总结集合类型选择指南动态数组需求优先使用ListT类型安全、性能优避免 ArrayListFIFO 场景使用QueueT如任务调度LIFO 场景使用StackT如撤销操作、递归模拟键值对存储使用DictionaryTKey, TValue无重复元素使用HashSetT三、字典在 C# 中哈希表Hashtable和字典DictionaryK,V是两种常用的键值对集合它们基于哈希算法实现高效的数据存储与检索。Hashtable传统非泛型哈希表核心概念Hashtable 是.NET 早期提供的非泛型键值对集合位于System.Collections命名空间其每个元素为DictionaryEntry类型的键值对。它通过键的哈希码组织数据支持快速的插入、查找和删除操作平均时间复杂度为 O (1)。底层结构与特性存储结构内部使用Bucket结构体数组存储数据每个Bucket包含键key、值val和哈希冲突标记hash_coll。冲突处理采用开放寻址法解决哈希冲突当哈希码冲突时通过线性探测寻找下一个可用位置。动态扩容当元素数量超过负载因子阈值默认 0.72时自动扩容并重新分配存储空间。键值限制键不可为null值可以为null键必须唯一通过GetHashCode()和Equals()保证唯一性。关键操作添加元素Add(object key, object value)键已存在时抛ArgumentException。索引器ht[key] value键存在时覆盖旧值不存在时新增。检索元素ContainsKey(key)判断键是否存在推荐使用命名更直观。ContainsValue(value)判断值是否存在时间复杂度 O (n)需遍历所有元素。TryGetValue模式通过ht.TryGetValue(key, out value)安全获取值避免键不存在时的异常。删除与清空Remove(key)删除指定键键不存在时无操作。Clear()清空所有元素保留容量不变。遍历通过foreach (DictionaryEntry entry in ht)遍历键值对。遍历中不可修改集合结构增删元素否则抛InvalidOperationException。DictionaryK,V泛型时代的优选核心概念DictionaryK,V 是泛型集合位于System.Collections.Generic专为类型安全设计避免了 Hashtable 的装箱拆箱操作性能更优。它同样基于哈希表实现键值对类型由泛型参数 K,V 指定。底层结构与特性存储结构由两个核心数组组成 ——_buckets桶数组存储条目索引和_entries条目数组存储实际键值对。冲突处理采用链地址法拉链法解决冲突每个桶通过next字段形成链表链接冲突的元素。动态扩容负载因子超过 0.72 时触发扩容新容量为原容量的 2 倍取最小质数。类型安全编译时检查键值类型避免运行时类型错误。底层原理图关键操作1.创建与初始化支持多种初始化方式推荐指定初始容量减少扩容次数var dict new Dictionarystring, int(100) { [Alice] 30, [Bob] 25 };2.添加与更新Add(K key, V value)键重复抛异常。索引器dict[key] value覆盖已有键的值。TryAdd(K key, V value)安全添加返回是否成功.NET Core 支持。3.检索与删除TryGetValue(K key, out V value)高效安全的取值方式。Remove(K key)删除并返回是否成功.NET Core 支持Remove(K key, out V value)同时获取删除的值。4.遍历遍历键值对foreach (var kvp in dict)kvp为KeyValuePairK,V。单独遍历键dict.Keys或值dict.Values。Hashtable 与 DictionaryK,V 的核心区别特性HashtableDictionaryK,V类型安全非泛型键值均为 object泛型编译时类型检查性能较慢存在装箱拆箱更快无装箱拆箱线程安全支持但性能低不支持需手动同步空值支持键不可为 null取决于 K/V 类型如 string 键可 null迭代顺序完全无序.NET Core 保留插入顺序适用场景兼容旧代码现代项目首选使用建议新项目优先选择 DictionaryK,V类型安全、性能更优是现代 C# 开发的推荐方案。多线程场景使用ConcurrentDictionaryK,V线程安全的泛型字典。旧项目维护若需兼容.NET Framework 早期版本Hashtable 仍可使用但建议逐步迁移至泛型集合。性能优化初始化时预估容量减少动态扩容次数自定义键类型需正确实现GetHashCode()和Equals()面试题字典里面也有一些面试题大家可以看一看思考一下1.什么是DictionaryTKey,TValue,它有哪些常用方法?2.C#中如何遍历Dictionary集合的四、泛型泛型Generics是 C# 中提升代码复用性与安全性的核心特性它允许开发者编写不依赖具体类型、可灵活适配多种数据的代码。泛型的本质与优势定义泛型通过在类、接口、方法或委托中引入类型参数Type Parameters实现 一次编写多类型适用 的代码复用。类型参数在实例化时被具体类型替换确保类型安全。核心优势类型安全编译时检查类型匹配避免运行时类型转换错误代码复用无需为每种数据类型重复编写逻辑相同的代码性能优化避免值类型的装箱 / 拆箱操作相比 object 类型传递可读性类型参数明确表达代码意图增强可维护性为什么需要泛型在泛型出现前解决多类型适配问题通常有两种方式重复编码为 int、string 等每种类型编写独立方法如ShowInt、ShowString代码冗余object 类型利用 object 是所有类型的基类特性统一处理但会导致装箱 / 拆箱值类型与引用类型转换损耗性能泛型通过延迟类型声明解决上述问题定义时不指定具体类型调用时再确定类型既保证复用性又避免性能损耗。泛型类型参数类型参数是泛型的核心作为 类型占位符 在使用时被具体类型替换语法示例泛型方法public static void ShowT(T tParameter) { Console.WriteLine($参数类型: {tParameter.GetType().Name}, 值: {tParameter}); }调用方式Showint(123); // 指定int类型 Showstring(hello); // 指定string类型工作原理编译时泛型代码生成 类型占位符如List运行时JIT 编译器将占位符替换为具体类型生成针对性的二进制代码泛型类与接口除方法外类和接口也可定义为泛型实现更灵活的类型抽象。泛型类定义public class GenericClassT { private T _value; public GenericClass(T value) _value value; public T GetValue() _value; }泛型接口定义public interface IGenericInterfaceT { T Process(T input); // 泛型方法声明 }使用注意泛型类型使用时必须指定具体类型如GenericClassint子类继承泛型类时可指定具体类型如class CommonClass : GenericClassint若子类也是泛型可保留类型参数如class CommonClassT : GenericClassT泛型约束泛型约束通过where关键字限制类型参数的范围确保其满足特定条件如继承某类、实现某接口等。常用约束类型约束语法说明where T : structT 必须是值类型非可空值类型where T : classT 必须是引用类型可包含 nullwhere T : new()T 必须有无参构造函数需放在约束列表最后where T : 基类名T 必须是指定基类或其派生类where T : 接口名T 必须实现指定接口可多接口约束where T : UT 必须是 U 或 U 的派生类U 为另一个类型参数代码示例// 组合约束T必须是引用类型、实现IDisposable、有无参构造函数 public class ComplexProcessorT where T : class, IDisposable, new() { public T CreateAndDispose() { T obj new T(); // 因new()约束可实例化 obj.Dispose(); // 因IDisposable约束可调用方法 return obj; } }总结泛型是 C# 中提升代码质量的关键特性通过类型参数实现灵活复用结合约束机制确保类型安全与逻辑合法性。合理使用泛型可显著减少冗余代码、提升性能并使代码意图更清晰是.NET 开发中的必备技能。题目分享题1实现一个泛型类要求可以返回传入的两个参数的最大值我的思路“用泛型做通用适配用 ref 保证外部生效用经典逻辑完成交换”首先以 “适配所有数据类型” 为目标选择泛型T定义交换方法SwipeT让方法能自动匹配传入变量的类型避免为int、string等不同类型重复编写相同逻辑同时通过ref关键字将参数设为引用传递解决值类型默认 “值传递” 导致 “方法内部交换不影响外部变量” 的问题确保交换操作能直接作用于外部原始变量交换逻辑采用经典的 “临时变量法”借助临时变量暂存值完成两个变量的互换保证逻辑简洁且适配任意可赋值类型最后在Main方法中调用泛型方法输出结果完整代码运行结果交换成功这道题还算简单下面我们看一道经典的冒泡排序题目题2实现一个泛型方法要求可以对传入的数组进行排序冒泡排序。实现思路“以泛型 接口约束实现通用适配 → 以参数校验保证健壮性 → 以优化版冒泡排序实现高效排序 → 以多类型测试验证通用性”方法采用泛型 IComparableT约束泛型T让方法成为 “类型占位符”调用时自动匹配数组的实际类型比如int[]传入时T会替换为intStudent[]传入时T替换为Student实现 “一套逻辑适配多类型”。where T : IComparableT约束冒泡排序需要比较元素大小而IComparableT接口是 C# 中 “类型可比较” 的标准约定提供CompareTo方法。这一约束确保传入的T类型一定支持比较操作避免了 “无法比较不同类型” 的错误。然后是参数校验排序前先判断arr null || arr.Length2若数组为空或元素不足 2 个无需排序直接返回 —— 这是代码健壮性的体现避免无效执行或空引用异常。最重要的还是冒泡排序的逻辑外层循环控制排序轮数定义int n arr.Length外层for (int i 0; i n-1; i)表示 “最多进行 n-1 轮排序”因为每轮会把当前最大元素 “冒泡” 到末尾剩余元素无需再比较它。内层循环相邻元素比较与交换内层for (int j 0; j n - i - 1; j)控制每轮的比较次数每轮后已排好的元素无需再比较所以次数随i增加而减少通过arr[j].CompareTo(arr[j1]) 0判断 “当前元素是否比下一个元素大”CompareTo是IComparableT的核心方法返回 0 表示当前元素更大若满足则用临时变量temp交换arr[j]和arr[j1]同时用swap true标记 “本轮发生了交换”。提前终止优化避免无效循环定义bool swap标记 “本轮是否发生交换”若某一轮swap为false说明数组已经完全有序直接break退出外层循环 —— 这能大幅减少后续的无效比较提升排序效率。最后在Main方法中输出一个是内置int[ ]数组还有1个是自定义Student[ ]数组验证对自定义类型的通用性需保证Student类实现了IComparableStudent接口才能被CompareTo方法比较。通过string.Join输出排序前后的结果直观验证排序效果。完整代码运行结果根据这个运行结果我们可以看到冒泡排序后的数组符合要求然后自定义数组Student[ ] 里的学生对象也是按照年龄升序排序的符合我们的预期结果这个泛型冒泡排序解题思路中最核心、最关键的一点是通过where T : IComparableT泛型约束为泛型类型T赋予 “可比较能力”—— 这是整个泛型排序能落地的前提也是泛型方法区别于 “单一类型排序” 的核心。“提前终止的 swap 标记” 是重要的性能优化避免数组已有序时的无效循环但这是 “冒泡排序的效率优化”而IComparableT约束是 “泛型排序能成立的根本”—— 没有这个约束泛型排序的核心目标通用适配所有可比较类型就无法实现。这周暂时分享这些题目下周我再分享一些面试题分享什么是HashSetT它的用途是什么五、总结字符串具有不变性修改创建新对象和驻留性相同字面量复用引用ReferenceEquals对值类型恒为 false受字符串驻留影响。集合ArrayList非泛型装箱拆箱、类型不安全ListT泛型类型安全、性能好推荐使用ListT排序需实现IComparable或用比较器。队列与栈队列 FIFO栈 LIFO栈用Pop遍历会删除元素foreach遍历不删除。泛型需注意约束如struct、class、new()等解决装箱拆箱问题提升性能与安全性。字典Hashtable非泛型、性能低已过时Dictionary泛型、性能高现代首选遍历Hashtable时修改会抛异常多线程用ConcurrentDictionary。下一期我打算总结I/O流、委托、多线程等内容敬请期待...