泛型
官方:延迟编写类或方法中的编程元素的数据类型,直到实际在程序中使用它。
个人理解:泛型就是一个可以与任何数据类型一起工作的类或方法。换句话说,就是用同一个方法来处理多个方法中功能相似但传入不同的数据类型
为什么使用泛型?
先说不用泛型,下面来举一个例子
public class CommonMethod
{
public static void ShowInt(int i)
{
Console.WriteLine("This is {0},type={1},parameter={2}",
typeof(CommonMethod).Name, i.GetType().Name, i);
}
public static void ShowString(string s)
{
Console.WriteLine("This is {0},type={1},parameter={2}",
typeof(CommonMethod).Name, s.GetType().Name, s);
}
public static void ShowDateTime(DateTime d)
{
Console.WriteLine("This is {0},type={1},parameter={2}",
typeof(CommonMethod).Name, d.GetType().Name, d);
}
}
结果
***********CommonMethod***************
This is CommonMethod,type=Int32,parameter=123
This is CommonMethod,type=String,parameter=456
This is CommonMethod,type=DateTime,parameter=2019/5/28 11:44:34
从上面的结果中我们可以看出这三个方法,除了传入的参数不同外,其里面实现的功能都是一样的。那如何进行优化呢?相信很多人会想到了OOP三大特性之一的继承,我们知道,C#语言中,object是所有类型的基类,下面用object进行优化
public static void ShowObject(object o)
{
Console.WriteLine("This is {0},type={1},parameter={2}",
typeof(CommonMethod), 0.GetType().Name, o);
}
结果
***********Object***************
This is ConsoleApp3.CommonMethod,type=Int32,parameter=123
This is ConsoleApp3.CommonMethod,type=String,parameter=456
This is ConsoleApp3.CommonMethod,type=DateTime,parameter=2019/5/28 11:55:35
从上述代码中,我们可以发现,object满足了要求,并且减少了代码冗余,但是却存在装箱和拆箱操作,损耗程序的性能。使用泛型会怎么样呢?
public static void Show<T>(T t)
{
Console.WriteLine("This is {0},type={1},parameter={2}",
typeof(CommonMethod), t.GetType().Name, t.ToString());
}
结果
***********Generic***************
This is ConsoleApp3.CommonMethod,type=Int32,parameter=123
This is ConsoleApp3.CommonMethod,type=String,parameter=456
This is ConsoleApp3.CommonMethod,type=DateTime,parameter=2019/5/28 12:05:33
调用
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
int a = 123;
string b = "456";
DateTime c = DateTime.Now;
Console.WriteLine("***********CommonMethod***************");
CommonMethod.ShowInt(a);
CommonMethod.ShowString(b);
CommonMethod.ShowDateTime(c);
Console.WriteLine("***********Object***************");
CommonMethod.ShowObject(a);
CommonMethod.ShowObject(b);
CommonMethod.ShowObject(c);
Console.WriteLine("***********Generic***************");
CommonMethod.Show<int>(a);
CommonMethod.Show<string>(b);
CommonMethod.Show<DateTime>(c);
Console.ReadKey();
}
}
}
结果
***********CommonMethod***************
This is CommonMethod,type=Int32,parameter=123
This is CommonMethod,type=String,parameter=456
This is CommonMethod,type=DateTime,parameter=2019/5/28 12:11:57
***********Object***************
This is ConsoleApp3.CommonMethod,type=Int32,parameter=123
This is ConsoleApp3.CommonMethod,type=String,parameter=456
This is ConsoleApp3.CommonMethod,type=DateTime,parameter=2019/5/28 12:11:57
***********Generic***************
This is ConsoleApp3.CommonMethod,type=Int32,parameter=123
This is ConsoleApp3.CommonMethod,type=String,parameter=456
This is ConsoleApp3.CommonMethod,type=DateTime,parameter=2019/5/28 12:11:57
为什么泛型可以解决上面的问题呢?
泛型是延迟声明的:即定义的时候没有指定具体的参数类型,把参数类型的声明推迟到了调用的时候才指定参数类型。 延迟思想在程序架构设计的时候很受欢迎。例如:分布式缓存队列、EF的延迟加载等等。
泛型究竟是如何工作的呢?
控制台程序最终会编译成一个exe程序,exe被点击的时候,会经过JIT(即时编译器)的编译,最终生成二进制代码,才能被计算机执行。泛型加入到语法以后,VS自带的编译器又做了升级,升级之后编译时遇到泛型,会做特殊的处理:生成占位符。再次经过JIT编译的时候,会把上面编译生成的占位符替换成具体的数据类型。