泛型(类和方法)
本课属于 Coddy C# 学习旅程的“面向对象编程”单元。第 42 课,共 70 课。
泛型让你能够编写适用于任何数据类型的类和方法,同时保证类型安全。你只需编写一个通用类来处理所有情况,而不必分别为 IntList、StringList 和 DoubleList 编写类。
泛型类使用类型参数,通常命名为 T,并用尖括号括起来:
public class Box<T>
{
private T content;
public void Store(T item) => content = item;
public T Retrieve() => content;
}
// 用于不同的数据类型
Box<int> intBox = new Box<int>();
intBox.Store(42);
Box<string> stringBox = new Box<string>();
stringBox.Store("Hello");创建 Box<int> 时,编译器会将每个 T 替换为 int。这样就能在编译时进行类型检查,你不会不小心把字符串存入 int 盒子中。
泛型方法的工作方式类似,可以让一个方法处理不同的类型:
public static void Swap<T>(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}
int x = 1, y = 2;
Swap(ref x, ref y); // x=2, y=1编译器会根据参数推断类型,因此你不需要显式写出 Swap<int>。泛型是 List<T> 和 Dictionary<TKey, TValue> 等集合的基础,可实现可复用且类型安全的代码。
挑战
简单让我们来构建一个通用的 Storage<T> 系统,用来存储和管理任意类型的项。你将创建一个可重复使用的容器类,展示泛型的强大之处:编写一次,就能用于整数、字符串或任何其他类型!
你需要将代码分成两个文件:
Storage.cs:在DataStorage命名空间中创建一个泛型Storage<T>类。你的存储容器应具备以下功能:- 包含一个用于存储项的
T类型私有数组,以及一个用于记录已存储项数量的Count属性 - 构造函数接受一个容量参数,用于初始化内部数组
- 包含一个
Add(T item)方法,在有剩余空间时添加项 - 包含一个
Get(int index)方法,返回指定索引处的项 - 包含一个
GetAll()方法,返回所有已存储的项,并用", "连接
- 包含一个用于存储项的
Program.cs:在主文件中展示你的泛型类如何处理两种不同的类型。创建一个Storage<int>和一个Storage<string>,分别向其中添加项,并展示同一个类如何顺畅地处理这两种类型。
你将收到 4 个输入:
- 要存储的第一个整数
- 要存储的第二个整数
- 要存储的第一个字符串
- 要存储的第二个字符串
创建一个容量为 5 的整数存储容器和一个容量为 5 的字符串存储容器。将两个整数添加到整数存储容器中,并将两个字符串添加到字符串存储容器中。
按以下格式打印输出:
Int storage: {GetAll()}
Int count: {Count}
First int: {Get(0)}
String storage: {GetAll()}
String count: {Count}
First string: {Get(0)}例如,如果输入是 42、100、Hello 和 World,输出应为:
Int storage: 42, 100
Int count: 2
First int: 42
String storage: Hello, World
String count: 2
First string: Hello注意,你只需编写一次 Storage<T> 类,它就能完美处理 int 和 string 两种类型,这就是泛型的妙处!编译器会确保类型安全,因此你不会意外地把字符串添加到整数存储容器中。
亲手试试
using System;
using DataStorage;
class Program
{
public static void Main(string[] args)
{
// 读取输入
int num1 = Convert.ToInt32(Console.ReadLine());
int num2 = Convert.ToInt32(Console.ReadLine());
string str1 = Console.ReadLine();
string str2 = Console.ReadLine();
// TODO: 创建一个容量为 5 的 Storage<int>
// TODO: 将两个整数添加到整数存储中
// TODO: 创建一个容量为 5 的 Storage<string>
// TODO: 将两个字符串添加到字符串存储中
// TODO: 按要求的格式打印输出
// Int storage: {GetAll()}
// Int 数量:{Count}
// 第一个 int:{Get(0)}
// String storage: {GetAll()}
// String count: {Count}
// First string: {Get(0)}
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: C# 在线编译器