C#泛型类
·
一、什么是泛型类?
泛型类是可以支持多种数据类型的类,它允许在定义类时不指定具体数据类型,而是在使用时动态指定。
核心作用:避免重复编写相似代码(如分别为int、string、object写相同逻辑的类),同时保证类型安全(编译时检查类型,避免装箱拆箱)。
二、为什么需要泛型类?
假设需要一个 "容器" 类存储数据,不使用泛型的问题:
- 针对每种类型写重复代码:如
IntContainer、StringContainer - 用
object兼容所有类型:会导致装箱拆箱(性能损耗)和类型转换错误(运行时才发现)
泛型类完美解决以上问题:一份代码支持所有类型,且编译时检查类型。
三、泛型类的定义语法
// 基本语法:类名后加<T>,T是类型参数(可自定义名称,如TData、TItem)
public class 类名<T>
{
// 可以使用T作为属性、方法参数、返回值的类型
private T _data;
public void SetData(T value)
{
_data = value;
}
public T GetData()
{
return _data;
}
}
四、泛型类的使用步骤
- 定义泛型类:用
<T>声明类型参数 - 创建实例:指定具体类型(如
int、string) - 调用成员:使用指定类型的数据操作
五、完整案例演示
案例 1:基础泛型容器类
using System;
// 1. 定义泛型容器类
public class DataContainer<T>
{
private T _data; // 用T作为字段类型
// 用T作为方法参数类型
public void Store(T value)
{
_data = value;
Console.WriteLine($"已存储:{_data}(类型:{typeof(T).Name})");
}
// 用T作为返回值类型
public T Retrieve()
{
return _data;
}
}
class Program
{
static void Main()
{
// 2. 使用泛型类:指定具体类型(int)
DataContainer<int> intContainer = new DataContainer<int>();
intContainer.Store(100); // 存储int类型
int num = intContainer.Retrieve(); // 直接获取int,无需转换
// 3. 切换类型为string
DataContainer<string> strContainer = new DataContainer<string>();
strContainer.Store("Hello 泛型"); // 存储string类型
string str = strContainer.Retrieve();
// 4. 甚至支持自定义类型
DataContainer<Person> personContainer = new DataContainer<Person>();
personContainer.Store(new Person { Name = "张三", Age = 20 });
Person p = personContainer.Retrieve();
}
}
// 自定义类型
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public override string ToString()
{
return $"{Name}({Age}岁)";
}
}
输出结果:
已存储:100(类型:Int32)
已存储:Hello 泛型(类型:String)
已存储:张三(20岁)(类型:Person)
案例 2:泛型集合类(模拟列表)
using System;
// 泛型列表类:支持动态添加和获取元素
public class MyList<T>
{
private T[] _items; // 用T数组存储元素
private int _count = 0;
public MyList(int capacity)
{
_items = new T[capacity];
}
// 添加元素(参数为T类型)
public void Add(T item)
{
if (_count < _items.Length)
{
_items[_count] = item;
_count++;
}
else
{
Console.WriteLine("列表已满!");
}
}
// 获取元素(返回值为T类型)
public T Get(int index)
{
if (index >= 0 && index < _count)
{
return _items[index];
}
throw new IndexOutOfRangeException("索引越界");
}
public int Count => _count; // 元素数量
}
class Program
{
static void Main()
{
// 创建存储int的列表
MyList<int> numbers = new MyList<int>(3);
numbers.Add(1);
numbers.Add(2);
numbers.Add(3);
Console.WriteLine("整数列表元素:");
for (int i = 0; i < numbers.Count; i++)
{
Console.WriteLine(numbers.Get(i)); // 直接获取int
}
// 创建存储string的列表
MyList<string> fruits = new MyList<string>(2);
fruits.Add("苹果");
fruits.Add("香蕉");
Console.WriteLine("\n字符串列表元素:");
for (int i = 0; i < fruits.Count; i++)
{
Console.WriteLine(fruits.Get(i)); // 直接获取string
}
}
}
输出结果:
整数列表元素:
1
2
3
字符串列表元素:
苹果
香蕉
六、泛型类的高级特性
1. 多个类型参数
可以定义多个类型参数(用逗号分隔),如<TKey, TValue>(模拟键值对):
public class KeyValuePair<TKey, TValue>
{
public TKey Key { get; set; }
public TValue Value { get; set; }
public KeyValuePair(TKey key, TValue value)
{
Key = key;
Value = value;
}
}
// 使用
var pair = new KeyValuePair<int, string>(1, "张三");
Console.WriteLine($"{pair.Key}: {pair.Value}"); // 输出:1: 张三
2. 类型约束(where 关键字)
限制泛型类型参数必须满足的条件(如必须是引用类型、必须实现某个接口等):
| 约束语法 | 说明 |
| where T : class | T 必须是引用类型(如 string、自定义类) |
| where T : struct | T 必须是值类型(如 int、bool) |
| where T : 接口名 | T 必须实现指定接口 |
| where T : 类名 | T 必须是指定类或其派生类 |
| where T : new() | T 必须有公开无参构造函数 |
案例:约束 T 必须实现IComparable接口(可比较大小)
// 泛型计算器:只能处理可比较的类型
public class Calculator<T> where T : IComparable<T>
{
public T Max(T a, T b)
{
// 调用IComparable接口的CompareTo方法
return a.CompareTo(b) > 0 ? a : b;
}
}
// 使用
Calculator<int> intCalc = new Calculator<int>();
Console.WriteLine(intCalc.Max(5, 10)); // 输出:10(int实现了IComparable)
Calculator<string> strCalc = new Calculator<string>();
Console.WriteLine(strCalc.Max("apple", "banana")); // 输出:banana(string实现了IComparable)
七、泛型类的优势总结
- 代码复用:一份代码支持所有类型,无需重复编写
- 类型安全:编译时检查类型,避免运行时类型转换错误
- 性能优化:避免值类型与
object之间的装箱拆箱(值类型直接操作) - 灵活性:通过类型约束控制泛型的适用范围,兼顾灵活性和安全性
八、常见疑问
Q:泛型类的类型参数名必须是 T 吗?
A:不是,可自定义(如TData、TItem),但习惯用T开头(Type 的缩写)。
Q:泛型类可以继承或实现接口吗?
A:可以,例如public class MyList<T> : IList<T>(C# 内置List<T>的实现方式)。
Q:泛型类的实例之间类型不同吗?
A:是的。DataContainer<int>和DataContainer<string>是两种不同的类型,不能互相转换。
更多推荐


所有评论(0)