-
泛型——类型安全的复用
泛型类与泛型方法
-
泛型的核心概念与价值
泛型是C#中用于创建类型无关、可重用代码的工具,核心解vb.net教程C#教程python教程SQL教程access 2010教程决以下问题:
类型安全:避免使用object类型导致的隐式类型转换错误;
性能优化:消除装箱/拆箱操作(值类型转object的开销);
代码复用:一套逻辑适配多种数据类型,减少重复代码。
泛型通过类型参数(如)实现,编译时会根据实际类型生成特定版本的代码,保证类型安全与性能。 -
泛型类:通用容器的实现
泛型类是包含类型参数的类,可适配任意数据类型。以下以通用列表容器MyList为例,展示泛型类的定义与使用。
2.1 非泛型vs泛型:问题对比
非泛型列表(如MyIntList)仅支持单一类型,代码复用性差:
csharp
// 非泛型:仅支持int类型的列表
public class MyIntList
{
private int[] _items;
private int _count;
public MyIntList() { _items = new int[10]; _count = 0; }
public void Add(int item) { _items[_count++] = item; }
public int Get(int index) { return _items[index]; }
}
泛型列表MyList
csharp
// 泛型类:支持任意类型的列表
public class MyList<T>
{
private T[] _items; // T为类型参数,编译时替换为实际类型
private int _count;
// 构造函数:初始化数组
public MyList()
{
_items = new T[10]; // 创建T类型的数组
_count = 0;
}
// 添加元素:接收T类型参数
public void Add(T item)
{
if (_count >= _items.Length) Array.Resize(ref _items, _items.Length*2);
_items[_count++] = item;
}
// 获取元素:返回T类型
public T Get(int index)
{
if (index <0 || index >= _count) throw new IndexOutOfRangeException();
return _items[index];
}
// 元素数量:只读属性
public int Count => _count;
}
2.2 泛型类的使用与逐行讲解
csharp
class Program
{
static void Main()
{
// 1. 泛型类实例化:指定类型参数为int
MyList<int> intList = new MyList<int>();
intList.Add(10);
intList.Add(20);
Console.WriteLine($"intList第0个元素:{intList.Get(0)}"); // 输出10
// 2. 指定类型参数为string
MyList<string> strList = new MyList<string>();
strList.Add("Hello");
strList.Add("泛型");
Console.WriteLine($"strList第1个元素:{strList.Get(1)}"); // 输出"泛型"
// 3. 指定类型参数为自定义类
MyList<Person> personList = new MyList<Person>();
personList.Add(new Person("张三",25));
Console.WriteLine($"personList第0个元素:{personList.Get(0).Name}"); // 输出"张三"
}
}
// 自定义类
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person(string name, int age) { Name = name; Age = age; }
}
逐行讲解:
MyList
intList.Add(10):Add方法接收int类型参数,无类型转换;
MyList
无装箱/拆箱操作:值类型(如int)直接存储,引用类型(如string、Person)存储地址,性能更高。
3. 泛型方法:类型无关的函数
泛型方法是包含类型参数的方法,可独立于类使用(静态/实例方法均可)。以下以Swap
3.1 泛型方法的定义与使用
csharp
public class GenericHelper
{
// 泛型方法:交换两个变量的值
public static void Swap<T>(ref T a, ref T b)
{
T temp = a; // T为类型参数,适配任意类型
a = b;
b = temp;
}
// 泛型方法:查找数组中的第一个元素
public static T FindFirst<T>(T[] array)
{
if (array == null || array.Length ==0) throw new ArgumentNullException();
return array[0];
}
}
// 使用示例
class Program
{
static void Main()
{
// 交换int变量
int x=10, y=20;
GenericHelper.Swap(ref x, ref y);
Console.WriteLine($"x={x}, y={y}"); // 输出x=20,y=10
// 交换string变量
string s1="A", s2="B";
GenericHelper.Swap(ref s1, ref s2);
Console.WriteLine($"s1={s1}, s2={s2}"); // 输出s1=B,s2=A
// 查找数组第一个元素
double[] nums = {3.14, 1.59, 2.65};
Console.WriteLine($"第一个元素:{GenericHelper.FindFirst(nums)}"); // 输出3.14
}
}
逐行讲解:
static void Swap
ref T a:使用ref关键字传递变量引用,确保交换生效;
GenericHelper.Swap(ref x, ref y):调用时无需显式指定
通用性:同一Swap方法适配int、string、自定义类等任意类型。
4. 泛型约束:限制类型参数范围
泛型约束通过where关键字限制类型参数的合法范围,确保泛型代码可调用特定方法/属性。常见约束如下:
4.1 常用约束类型
约束语法 作用说明
where T : class T必须是引用类型(如string、类)
where T : struct T必须是值类型(如int、double)
where T : new() T必须有默认构造函数(无参)
where T : BaseClass T必须继承自BaseClass
where T : IInterface T必须实现IInterface接口
4.2 约束实例:带比较的泛型类
以下示例要求类型参数T实现IComparable
csharp
// 泛型类:查找数组中的最大值
public class MaxFinder<T> where T : IComparable<T>
{
public static T FindMax(T[] array)
{
if (array == null || array.Length ==0) throw new ArgumentNullException();
T max = array[0];
foreach (var item in array)
{
if (item.CompareTo(max) >0) max = item; // 调用IComparable<T>的CompareTo方法
}
return max;
}
}
// 使用示例
class Program
{
static void Main()
{
int[] ints = {5,2,9,1};
Console.WriteLine($"int最大值:{MaxFinder<int>.FindMax(ints)}"); // 输出9
string[] strs = {"apple", "banana", "cherry"};
Console.WriteLine($"string最大值:{MaxFinder<string>.FindMax(strs)}"); // 输出"cherry"
}
}
讲解:
where T : IComparable
int、string均实现IComparable
若传入未实现该接口的类型(如自定义类未实现IComparable
5. 基础知识拓展
5.1 泛型的协变与逆变
C#通过out(协变)和in(逆变)关键字,允许泛型类型在继承关系中的灵活转换:
协变(out):用于输出类型(如返回值),允许将IEnumerable
本站原创,转载请注明出处:










