泛型Generic 允许一个可以与任何数据类型一起工作的类或方法
优点:
1.性能
不需要拆箱和装箱
2.类型安全
和object类相比,可以根据需要用特定的类型替换泛型类型,保证了数据安全类。
3.二进制代码重用
一次定义多次使用
4.代码的扩展
对于引用类型,会共享本地类的所有相同代码。只有值类型,才会每次实例化一个新类
特性:
使用泛型是一种增强程序功能的技术,具体如下:
1.利于最大程度地重用代码、保护类型的安全以及提高性能。
2.可以创建泛型集合类。.NET框架类库在System.Collections.Generic命名空间中包含了一些新的泛型集合类。您可以使用这些泛型集合类来替代System.Collections中的集合类
3.可以自己创建泛型接口,泛型类,泛型方法,泛型事件和泛型委托
4.可以对泛型类进行约束以访问特定数据类型的方法
5.关于泛型数据类型中使用的类型的信息可在运行时通过使用反射获取
组成:
1.泛型类
public class MyGenericArray<T>
{
private T[] array;
public MyGenericArray(int size) {
array = new T[size + 1];
}
public T getItem(int index) {
return array[index];
}
public void setItem(int index,T value) {
array[index] = value;
}
}
2.泛型接口
https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/generics/generic-interfaces
3.泛型结构
https://www.cnblogs.com/Luoma_HaoWei/p/3278452.html
4.泛型方法
using System;
using System.Collections.Generic;
namespace GenericMethodAppl
{
class Program
{
static void Swap<T>(ref T lhs, ref T rhs)
{
T temp;
temp = lhs;
lhs = rhs;
rhs = temp;
}
static void Main(string[] args)
{
int a, b;
char c, d;
a = 10;
b = 20;
c = 'I';
d = 'V';
// 在交换之前显示值
Console.WriteLine("Int values before calling swap:");
Console.WriteLine("a = {0}, b = {1}", a, b);
Console.WriteLine("Char values before calling swap:");
Console.WriteLine("c = {0}, d = {1}", c, d);
// 调用 swap
Swap<int>(ref a, ref b);
Swap<char>(ref c, ref d);
// 在交换之后显示值
Console.WriteLine("Int values after calling swap:");
Console.WriteLine("a = {0}, b = {1}", a, b);
Console.WriteLine("Char values after calling swap:");
Console.WriteLine("c = {0}, d = {1}", c, d);
Console.ReadKey();
}
}
}
约束类型
约束 | 说明 |
where T:struct | 结构约束,T必须是值类型 |
where T:class | T必须是引用类型 |
where T:IFoo | T必须实现接口IFoo |
where T:Foo | T必须派生自基类Foo |
where T:new() | 构造函数约束,指定类型T必须有一个默认的构造函数 |
where T1:T2 | T1必须派生自T2,该约束也称为裸类型约束 |
为什么泛型可以做到呢?
泛型是延迟声明的:即定义的时候没有指定具体的参数类型,把参数类型的声明推迟到了调用的时候才指定参数类型。 延迟思想在程序架构设计的时候很受欢迎。例如:分布式缓存队列、EF的延迟加载等等。
泛型究竟是如何工作的呢?
控制台程序最终会编译成一个exe程序,exe被点击的时候,会经过JIT(即时编译器)的编译,最终生成二进制代码,才能被计算机执行。泛型加入到语法以后,VS自带的编译器又做了升级,升级之后编译时遇到泛型,会做特殊的处理:生成占位符。再次经过JIT编译的时候,会把上面编译生成的占位符替换成具体的数据类型。