泛型是C#语言的一项强大特性,它允许在定义类、接口、方法等时,不指定具体的数据类型,而是在使用时才指定。这种设计不仅提升了代码的复用性,还在编译时提供了类型安全,避免了因类型转换而引发的错误。
概念
泛型使用占位符T来代表某种类型,编译期间可以决定具体的类型
其中占位符不一定非要用 T 来表示, 也可以用其他字符或者名字来代替
T 是类型占位符,表示还没决定具体是什么类型,先把这个类型的位置给站住
泛型类
cs
class MyGeneric<T>
{
}
示例
cs
using System;
namespace 泛型
{
class Count<T>
{
public void Value(T a)
{
Console.WriteLine(a);
}
}
internal class Program
{
static void Main(string[] args)
{
Count<int> count = new Count<int>();
count.Value(1);
Count<double> count1 = new Count<double>();
count1.Value(1.10);
Console.ReadKey();
}
}
}
这里表示的是创建一个泛型类Count,类型为T,在类里面有一个Value方法,输出a的值,在主函数里面实例化count,这时:T的类型就会转变为int类型,然后将a的值赋值为1,打印,也可以声明为double类型,同理这里就不做过多解释了。
泛型方法
通过 "参数化类型", 实现在同一份代码上可以操作多种数据类型
示例
cs
using System;
namespace 泛型
{
internal class Program
{
//交换两个变量的值
static public void S<T>( T a, T b)
{
T temp = a;
a = b;
b = temp;
}
static void Main(string[] args)
{
int m = 10, n = 20;
S<int>(m, n);
Console.ReadKey();
}
}
}
注:
cs
//求两个变量的和
static public T Add<T>(T a, T b)
{
return a + b;
}
当我们想要做一个求两个变量的和时,就会产生如下报错
++此时,我们就需要一个解决方法啊!++
dynamic关键字:
含义:在程序的编译期间,不去进行验证,而是将类型校验推迟到运行的时候。
此时报错就消失了,呃呃呃呃呃~~~
cs
Console.WriteLine(Add<int>(1, 2));
在主函数加上这行代码输出:3
泛型特征
- 泛型可以提供多种类型的占位符
cs
class Store<T, V>
{
public T[] Arr1{get; set;}
public V[] Arr2{get; set;}
}
用这行代码表示就比较清晰一点:Store<int, float> s = new Store<int, float>(); 此时 T 就是 int 类型,V 就是 float 类型
- 泛型类可以被继承,子类可以指定父类泛型的具体类型, 子类也可以作为泛型类
cs
class Person<T>
{
public T Id { get; set; }
}
//将父类型进行特化,然后继承
class Teacher1 : Person<int>
{
}
//无法决定继承的泛型类型
class Teacher2<V> : Person<V>
{
}
泛型接口
泛型接口允许在定义接口时使用类型参数
cs
public interface IRepository<T>
{
void Add(T item);
T Get(int id);
}
这个接口定义了一个通用的存储库,具体实现时需要提供 T
的具体类型
小结
使用泛型是一种增强程序功能的技术,具体表现在以下几个方面:
- 它有助于您最大限度地重用代码、保护类型的安全以及提高性能。
- 您可以创建泛型集合类。.NET 框架类库在 System.Collections.Generic 命名空间中包含了一些新的泛型集合类。您可以使用这些泛型集合类来替代 System.Collections 中的集合类。
- 您可以创建自己的泛型接口、泛型类、泛型方法、泛型事件和泛型委托。
- 您可以对泛型类进行约束以访问特定数据类型的方法。
- 关于泛型数据类型中使用的类型的信息可在运行时通过使用反射获取。