一、什么是泛型类?

泛型类是可以支持多种数据类型的类,它允许在定义类时不指定具体数据类型,而是在使用时动态指定。

核心作用:避免重复编写相似代码(如分别为intstringobject写相同逻辑的类),同时保证类型安全(编译时检查类型,避免装箱拆箱)。

二、为什么需要泛型类?

假设需要一个 "容器" 类存储数据,不使用泛型的问题:

  1. 针对每种类型写重复代码:如IntContainerStringContainer
  2. object兼容所有类型:会导致装箱拆箱(性能损耗)和类型转换错误(运行时才发现)

泛型类完美解决以上问题:一份代码支持所有类型,且编译时检查类型。

三、泛型类的定义语法
// 基本语法:类名后加<T>,T是类型参数(可自定义名称,如TData、TItem)
public class 类名<T>
{
    // 可以使用T作为属性、方法参数、返回值的类型
    private T _data;

    public void SetData(T value)
    {
        _data = value;
    }

    public T GetData()
    {
        return _data;
    }
}
四、泛型类的使用步骤
  1. 定义泛型类:用<T>声明类型参数
  2. 创建实例:指定具体类型(如intstring
  3. 调用成员:使用指定类型的数据操作
五、完整案例演示
案例 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 : classT 必须是引用类型(如 string、自定义类)
where T : structT 必须是值类型(如 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)
七、泛型类的优势总结
  1. 代码复用:一份代码支持所有类型,无需重复编写
  2. 类型安全:编译时检查类型,避免运行时类型转换错误
  3. 性能优化:避免值类型与object之间的装箱拆箱(值类型直接操作)
  4. 灵活性:通过类型约束控制泛型的适用范围,兼顾灵活性和安全性
八、常见疑问

Q:泛型类的类型参数名必须是 T 吗?

A:不是,可自定义(如TDataTItem),但习惯用T开头(Type 的缩写)。

Q:泛型类可以继承或实现接口吗?

A:可以,例如public class MyList<T> : IList<T>(C# 内置List<T>的实现方式)。

Q:泛型类的实例之间类型不同吗?

A:是的。DataContainer<int>DataContainer<string>是两种不同的类型,不能互相转换。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐