# 一、泛型方法中 T 的含义与作用1. **T 表示类型参数**T 是一个**占位符**代表**任意一种数据类型**。在方法定义时不确定具体类型调用时才确定。2. **T 可以是任意类型**包括- 值类型int、double、bool、char、struct- 引用类型string、类、数组、接口、、、csharpusing System;class Program{// 定义泛型方法T 为类型占位符public static void ShowInfoT(T data){Console.WriteLine($数据值{data}数据类型{typeof(T)});}static void Main(){// 1. 值类型调用ShowInfoint(100);ShowInfodouble(3.14);ShowInfobool(true);ShowInfochar(A);// 2. 引用类型调用ShowInfostring(测试字符串);ShowInfoobject(new object());// 编译器可自动推断类型省略 TShowInfo(666);ShowInfo(自动推断类型);Console.ReadKey();}}3. **类型推导机制**调用泛型方法时**编译器会根据传入参数自动推导 T 的类型**不需要手动写 int / string。4. **泛型的核心优势**一套代码支持所有类型**避免重复代码、避免类型转换、提高安全性**。、、、csharpusing System;class GenericDemo{// 泛型方法public static void PrintDataT(T value){Console.WriteLine($值{value}类型{typeof(T).Name});}static void Main(){// 1. 类型推导省略 类型编译器自动识别PrintData(100); // 自动推导 T intPrintData(3.14); // 自动推导 T doublePrintData(Hello); // 自动推导 T stringPrintData(true); // 自动推导 T bool// 也可以手动指定类型两种写法都合法PrintDatastring(手动指定字符串类型);// 对比不用泛型需要写多个重载方法代码冗余// public static void Print(int a){}// public static void Print(double a){}// public static void Print(string a){}Console.ReadKey();}}# 二、泛型的重要限制未约束 T 不能直接使用 运算符1. **未约束的泛型 T编译器不知道它是什么类型**不知道是否支持 、-、*、/ 等运算符。2. **直接对 T 类型变量做数学运算会编译报错**因为编译器无法验证运算是否合法。3. **解决方式**- 使用**泛型约束**- 使用动态类型 dynamic- 使用运算符重载或第三方库辅助4. **核心结论必背****无约束的泛型 T 不能直接进行算术运算。**、、、csharpusing System;class Program{// 无约束泛型方法public static void CalcT(T a, T b){// 编译报错无约束 T 不能直接使用 运算符// T result a b;}// 方式1使用 dynamic 绕过限制public static void AddByDynamicT(T a, T b){dynamic d1 a;dynamic d2 b;var res d1 d2;Console.WriteLine($运算结果{res});}static void Main(){AddByDynamic(10, 20);AddByDynamic(3.14, 2.86);Console.ReadKey();}}# 三、方法重载优先级固定类型方法 泛型方法1. **同一个类中普通方法固定类型与泛型方法可构成重载**2. **重载匹配规则考试必考****精确匹配的普通方法 泛型方法**传入 int → 优先调用 int 方法传入 string → 优先调用 string 方法无精确匹配时才会调用泛型方法。3. **为什么**普通方法是**明确类型**泛型是**通用类型**编译器永远优先选择**最具体、最精确**的方法。4. **必背结论****固定类型方法优先级 泛型方法。**、、、csharpusing System;class Test{// 普通 int 类型方法public static void Show(int num){Console.WriteLine(调用 int 普通方法 num);}// 普通 string 类型方法public static void Show(string str){Console.WriteLine(调用 string 普通方法 str);}// 泛型方法public static void ShowT(T data){Console.WriteLine($调用泛型方法类型{typeof(T).Name}值{data});}static void Main(){// 1. 精确匹配优先执行对应普通方法Show(100);Show(C#);// 2. 无对应普通方法才会调用泛型方法Show(3.14);Show(true);Console.ReadKey();}}# 四、泛型类继承普通类非泛型类的规则1. **泛型类可以继承非泛型普通类**语法class GenericClassT : NormalClass2. **继承后父类成员完全可用**子类可以直接访问父类的字段、属性、方法。3. **泛型参数 T 只作用于当前泛型类不影响父类**父类是普通类与 T 无关。T 只在子类内部生效。4. **语法合法、使用广泛**常用于通用工具类、通用管理类、通用模型。5. **核心结论****泛型类可以正常继承非泛型类继承关系不受泛型影响。**、、、csharpusing System;// 非泛型父类普通类class ParentClass{public string Name { get; set; }public void SayHello(){Console.WriteLine(来自普通父类的方法Hello);}}// 泛型子类 继承 普通父类class ChildClassT : ParentClass{// 泛型类独有的泛型成员public T Data { get; set; }public void ShowData(){Console.WriteLine($泛型数据{Data}类型{typeof(T).Name});}}class Program{static void Main(){// 使用 int 作为泛型参数ChildClassint obj1 new ChildClassint();// 调用父类属性和方法obj1.Name 测试1;obj1.SayHello();// 调用自身泛型成员obj1.Data 100;obj1.ShowData();Console.WriteLine(------------------);// 使用 string 作为泛型参数ChildClassstring obj2 new ChildClassstring();obj2.Name 测试2;obj2.SayHello();obj2.Data 泛型字符串;obj2.ShowData();Console.ReadKey();}}# 五、四条知识点 终极精简背诵版最适合记忆1. **T 类型参数调用时自动推导支持任意类型。**2. **无约束 T 不能直接运算因为编译器不知道类型。**3. **方法重载普通固定类型方法 优先于 泛型方法。**4. **泛型类可继承普通类父类不受 T 影响子类正常使用父类成员。**
C# 泛型
# 一、泛型方法中 T 的含义与作用1. **T 表示类型参数**T 是一个**占位符**代表**任意一种数据类型**。在方法定义时不确定具体类型调用时才确定。2. **T 可以是任意类型**包括- 值类型int、double、bool、char、struct- 引用类型string、类、数组、接口、、、csharpusing System;class Program{// 定义泛型方法T 为类型占位符public static void ShowInfoT(T data){Console.WriteLine($数据值{data}数据类型{typeof(T)});}static void Main(){// 1. 值类型调用ShowInfoint(100);ShowInfodouble(3.14);ShowInfobool(true);ShowInfochar(A);// 2. 引用类型调用ShowInfostring(测试字符串);ShowInfoobject(new object());// 编译器可自动推断类型省略 TShowInfo(666);ShowInfo(自动推断类型);Console.ReadKey();}}3. **类型推导机制**调用泛型方法时**编译器会根据传入参数自动推导 T 的类型**不需要手动写 int / string。4. **泛型的核心优势**一套代码支持所有类型**避免重复代码、避免类型转换、提高安全性**。、、、csharpusing System;class GenericDemo{// 泛型方法public static void PrintDataT(T value){Console.WriteLine($值{value}类型{typeof(T).Name});}static void Main(){// 1. 类型推导省略 类型编译器自动识别PrintData(100); // 自动推导 T intPrintData(3.14); // 自动推导 T doublePrintData(Hello); // 自动推导 T stringPrintData(true); // 自动推导 T bool// 也可以手动指定类型两种写法都合法PrintDatastring(手动指定字符串类型);// 对比不用泛型需要写多个重载方法代码冗余// public static void Print(int a){}// public static void Print(double a){}// public static void Print(string a){}Console.ReadKey();}}# 二、泛型的重要限制未约束 T 不能直接使用 运算符1. **未约束的泛型 T编译器不知道它是什么类型**不知道是否支持 、-、*、/ 等运算符。2. **直接对 T 类型变量做数学运算会编译报错**因为编译器无法验证运算是否合法。3. **解决方式**- 使用**泛型约束**- 使用动态类型 dynamic- 使用运算符重载或第三方库辅助4. **核心结论必背****无约束的泛型 T 不能直接进行算术运算。**、、、csharpusing System;class Program{// 无约束泛型方法public static void CalcT(T a, T b){// 编译报错无约束 T 不能直接使用 运算符// T result a b;}// 方式1使用 dynamic 绕过限制public static void AddByDynamicT(T a, T b){dynamic d1 a;dynamic d2 b;var res d1 d2;Console.WriteLine($运算结果{res});}static void Main(){AddByDynamic(10, 20);AddByDynamic(3.14, 2.86);Console.ReadKey();}}# 三、方法重载优先级固定类型方法 泛型方法1. **同一个类中普通方法固定类型与泛型方法可构成重载**2. **重载匹配规则考试必考****精确匹配的普通方法 泛型方法**传入 int → 优先调用 int 方法传入 string → 优先调用 string 方法无精确匹配时才会调用泛型方法。3. **为什么**普通方法是**明确类型**泛型是**通用类型**编译器永远优先选择**最具体、最精确**的方法。4. **必背结论****固定类型方法优先级 泛型方法。**、、、csharpusing System;class Test{// 普通 int 类型方法public static void Show(int num){Console.WriteLine(调用 int 普通方法 num);}// 普通 string 类型方法public static void Show(string str){Console.WriteLine(调用 string 普通方法 str);}// 泛型方法public static void ShowT(T data){Console.WriteLine($调用泛型方法类型{typeof(T).Name}值{data});}static void Main(){// 1. 精确匹配优先执行对应普通方法Show(100);Show(C#);// 2. 无对应普通方法才会调用泛型方法Show(3.14);Show(true);Console.ReadKey();}}# 四、泛型类继承普通类非泛型类的规则1. **泛型类可以继承非泛型普通类**语法class GenericClassT : NormalClass2. **继承后父类成员完全可用**子类可以直接访问父类的字段、属性、方法。3. **泛型参数 T 只作用于当前泛型类不影响父类**父类是普通类与 T 无关。T 只在子类内部生效。4. **语法合法、使用广泛**常用于通用工具类、通用管理类、通用模型。5. **核心结论****泛型类可以正常继承非泛型类继承关系不受泛型影响。**、、、csharpusing System;// 非泛型父类普通类class ParentClass{public string Name { get; set; }public void SayHello(){Console.WriteLine(来自普通父类的方法Hello);}}// 泛型子类 继承 普通父类class ChildClassT : ParentClass{// 泛型类独有的泛型成员public T Data { get; set; }public void ShowData(){Console.WriteLine($泛型数据{Data}类型{typeof(T).Name});}}class Program{static void Main(){// 使用 int 作为泛型参数ChildClassint obj1 new ChildClassint();// 调用父类属性和方法obj1.Name 测试1;obj1.SayHello();// 调用自身泛型成员obj1.Data 100;obj1.ShowData();Console.WriteLine(------------------);// 使用 string 作为泛型参数ChildClassstring obj2 new ChildClassstring();obj2.Name 测试2;obj2.SayHello();obj2.Data 泛型字符串;obj2.ShowData();Console.ReadKey();}}# 五、四条知识点 终极精简背诵版最适合记忆1. **T 类型参数调用时自动推导支持任意类型。**2. **无约束 T 不能直接运算因为编译器不知道类型。**3. **方法重载普通固定类型方法 优先于 泛型方法。**4. **泛型类可继承普通类父类不受 T 影响子类正常使用父类成员。**