泛型方法就是一个方法能满足不同类型的方法。
1.object是所有类的基类,所以也可以实现和泛型一样的功能(比如接收参数的时候可以接收任何类型的参数),但是使用object存在2个缺陷
(1)类型安全问题
(2)性能问题(拆箱和装箱,其中涉及到了值类型和引用类性)
object是引用类型,比如方法接收一个int参数,首先要将int转为object,此时需要在堆中开辟空间存储值,进入方法内部实际使用的时候需要拆箱,就是将堆中存储的数据取出来放到栈中,这个过程会损失性能。
(3)泛型为什么能识别任何类型?
如下,是c#语言编译的过程, CLR是托管程序运行的环境,就像Windows是普通的PE程序的运行环境一样,JIT即时编编译,是.NET运行可执行程序的基本方式,比在真正运行的时候IL才会被JIT编译成机器指令。
注意:泛型是框架升级之后所带的功能,不是语法糖
(4)调用方式
明确限制传入类型:此时已经限制了只能传int类型,传别的类型会报错。
public void Template() { int s = 0; Test<int>(s); } /// <summary> /// 声明一个泛型方法 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="test"></param> public void Test<T>(T test) { }
第二种是由编译器编译出来传入的类型,不明显指定:
public void Template() { int s = 0; Test(s); }
(5)性能对比:泛型>普通方法>object(前提是在大量数据数据情况下,数据量不是很大的时候其实差距可以忽略不计)
2.泛型缓存 (泛型缓存性能要大于普通的缓存)
(1)在这之前先做一个使用静态属性常驻内存的缓存形式,这也是比较常用的。
public class Program { static void Main(string[] args) { TestCashe.GetCashe("1"); } } public class TestCashe { public static Dictionary<string, string> _dic = null; static TestCashe() { Console.WriteLine("构造静态函数"); _dic = new Dictionary<string, string>(); } //存储/获取 缓存数据 public static string GetCashe(string key) { if (!_dic.ContainsKey(key)) { _dic[key] = DateTime.Now.ToString(); } Console.WriteLine($"输出{_dic[key]}"); return _dic[key]; } }
结果:
构造静态函数
输出2021/8/14 20:01:24
(2)泛型类型会针对传入的不同类型生成对应的副本,比如一个正常的类中的一个静态构造函数,在new这个类的时候,只会执行一遍这个静态构造函数,但是在泛型类中,如果传入的这个类型是第一次进入,就会执行静态函数,如果第二次再传已经传入过的类型之后静态构造函数就不会再执行了,因为这个类型的副本已经存在了。
namespace MyDelegateExtend { public class Program { static void Main(string[] args) { TestCashe<int>.GetCashe(); } } public class TestCashe<T> { public static string _str = null; static TestCashe() { _str = $"类型:{typeof(T).FullName},时间: DateTime.Now.ToString()"; Console.WriteLine($"构造静态函数:{DateTime.Now.ToString()},类型:{typeof(T)}"); } //存储/获取 缓存数据 public static string GetCashe() { Console.WriteLine($"输出:{_str}"); return _str; } } }
结果:
构造静态函数:2021/8/14 19:55:27,类型:System.Int32
输出:类型:System.Int32,时间: DateTime.Now.ToString()