Loading... 下面用**最短路径**把 C# 泛型说清楚,并给出可直接运行的小例子与图表 ✅ ## 一、为什么要用 泛型? * 提升 类型安全:编译期检查,减少运行时异常。 * 提升 性能:避免值类型装箱/拆箱。 * 提升 复用性:一次实现,多种类型可用。🧩 --- ## 二、案例1:最小可用的泛型类(Box<T>) ```csharp public class Box<T> { public T Value { get; } public Box(T value) => Value = value; public bool IsDefault() => Equals(Value, default(T)); } // 使用 var iBox = new Box<int>(42); var sBox = new Box<string>("hello"); ``` **解释**: * `Box<T>` 用类型形参 `T` 承载任意类型;`Value` 即存放的具体值。 * `IsDefault()` 用于判断是否等于类型的默认值(如 `0`、`null` 等);体现了 泛型的通用性。 * 使用时:`Box<int>`、`Box<string>` 分别实例化,不会发生装箱,保持 性能。 --- ## 三、案例2:泛型方法 + 交换(Swap) ```csharp public static class Utils { public static void Swap<T>(ref T a, ref T b) { (a, b) = (b, a); } } // 使用 int x = 1, y = 9; Utils.Swap(ref x, ref y); // 交换 int string a = "A", b = "B"; Utils.Swap(ref a, ref b); // 交换 string ``` **解释**: * `Swap<T>` 是**泛型方法**,只关心“有两个相同类型的变量”,与具体类型无关。 * `ref` 引用传递能原地交换,提高 效率。 * 展示了 复用性:相同实现覆盖多种类型。 --- ## 四、案例3:约束 where + 比较(寻找最小值) ```csharp public static T MinOf<T>(IEnumerable<T> source) where T : IComparable<T> { using var e = source.GetEnumerator(); if (!e.MoveNext()) throw new InvalidOperationException("空序列"); T min = e.Current; while (e.MoveNext()) if (e.Current.CompareTo(min) < 0) min = e.Current; return min; } // 使用 var nums = new[] { 7, 3, 9 }; var texts = new[] { "c", "a", "b" }; Console.WriteLine(MinOf(nums)); // 3 Console.WriteLine(MinOf(texts)); // a ``` **解释**: * `where T : IComparable<T>` 是 泛型约束,要求 `T` 可比较,编译器才能放心调用 `CompareTo`。 * 泛型 + 约束 = **既通用又可验证**,避免运行期反射或类型判断。 --- ## 五、(可选)现代用法:.NET 7+ 泛型数值(泛型“加法”)🚀 ```csharp // 需要 <TargetFramework>net7.0+</TargetFramework> using System.Numerics; public static T Sum<T>(IEnumerable<T> source) where T : INumber<T> { T sum = T.Zero; foreach (var x in source) sum += x; return sum; } // 使用:int/long/decimal/float/double 等都可直接求和 var total = Sum(new[] { 1, 2, 3, 4 }); // 10 ``` **解释**: * `INumber<T>` 是 .NET 的“数值泛型接口”,让加减乘除等运算**在泛型里静态绑定**,避免装箱与分支。 * 体现新一代 泛型约束能力,更强更快。 --- ## 六、速查对照表(vditor/Markdown 支持) | 概念 | 作用 | 典型写法 | 价值 | | ---------- | ------------- | --------------------------- | ---------------- | | 泛型类 | 抽象容器/服务 | `class Box<T>` | 复用、避免装箱 | | 泛型方法 | 抽象算法 | `void Swap<T>(...)` | 一次实现多处可用 | | 约束 where | 类型特性保证 | `where T: IComparable<T>` | 编译期安全 | | 数值泛型 | 统一数值运算 | `where T: INumber<T>` | 性能与可读性 | | 默认值 | 统一空值语义 | `default(T)` | 通用判空 | --- ## 七、工作流程图:我该不该用 泛型? ```mermaid flowchart LR A[是否需要复用到不同类型?] -->|是| B[抽象为泛型类/方法] A -->|否| C[保持具体类型即可] B --> D{是否依赖特定能力?} D -->|是| E[添加 where 约束 (接口/基类/new)] D -->|否| F[直接实现] E --> G[单元测试/性能验证] F --> G ``` --- ## 八、实践建议 ✅ 1. 优先以**接口约束**表达需求(如 `IComparable<T>`、`IEnumerable<T>`),增强 类型安全。 2. 涉及数值运算时考虑 INumber<T>,保持统一实现与高性能。 3. 先写**非泛型**原型验证可行性,再抽象成 泛型;避免过度设计。🙂 > 有了以上 3 个小例子,你已经能在项目中安心落地 C# 泛型:容器、算法、约束与现代数值运算一应俱全。需要我把你现有的工具类改造成**泛型+约束**版本并做基准测试吗? 最后修改:2025 年 09 月 13 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏