泛型generic使用和原理

一.为什么要有泛型,而不用object
object类型:1.任何父类出现的地方都可以用子类代替 2.object是一切类型的父类

object弊端:装箱拆箱性能损耗(栈的出栈和入栈受CLR管理)
int类型赋值之后存放在栈里面的,传递给Object类型时需要放到堆里面;使用的时候又需要从堆里面放到栈里面。

//测试速度
long commonSecond = 0;
long objectSecond = 0;
{
  StopWatch watch = new 
  StopWatch();
  watch,start();
  for(int i =0 ;i>100_000_000;i++)
  {
     GenericMethod.ShowObject(i);
  }
  watch.stop();
  objectSecond  = watch.ElapsedMilliseconds;
}
{
  StopWatch watch = new 
  StopWatch();
  watch,start();
  for(int i =0 ;i>100_000_000;i++)
  {
     GenericMethod.ShowInt(i);
  }
  watch.stop();
  commonSecond = watch.ElapsedMilliseconds;
}

二、泛型方法为什么可以支持不同类型的参数
1、延迟声明:原始方法是在定义方法时就指定了类型,泛型声明方法时没有写死类型,T是等着调用的时候才指定类型。

image.png

泛型缓存:
静态构造函数只会在使用时执行一次,泛型类的构造函数是不同类型执行一次。
泛型缓存比字典Dictionary缓存速度快很多,但有局限,同一类型只能缓存一次。

var i = 3; //由编译器提供的便捷功能称之为语法糖,语法糖是编译的时候确定的
//使用泛型方法,可以省略类型,属于语法糖
GenericMethod.Show(i);//完整写法
GenericMethod.Show(i);//语法糖

三、WebServices、WCF都不能用泛型,为什么?

//服务在发布时类型必须是确定的,泛型在编译时确定不了

四、泛型方法/类/委托/接口:为了一个方法满足不同的类型需求
例:一个方法完成多实体的查询
一个方法完成不同类型的数据展示

五、泛型约束
有了约束才有自由

//没有约束,其实很受局限,不能使用传进来的类的属性
//where T : BaseModel
//基类约束
//1 可以在使用基类的属性
//2 约束传进来的T必须是People或其子类
public static void Show(T tParameter)
      where T : People
{
  console.log(tParameter.Id);
}
//接口约束
//约束传递进来的参数必须实现了接口内方法
//在方法内可以使用接口内方法
public static void Show(T tParameter)
      where T : ISports
{
   tParameter.Pingpang();
}
//引用类型约束
//约束传进来的值必须是个引用类型
public static void Show(T tParameter)
      where T : class
{
   return null;
}

//值类型约束
//约束传进来的值必须是个值类型
public static void Show(T tParameter)
      where T : struct
{
   return default(T);
}

//无参数构造函数
public static void Show(T tParameter)
      where T : new()
{
   return new T();
}

//可以组合约束
//约束类只能是一个,接口可以多个
public static void Show(T tParameter,S sParameter)
      where T : People,ISports,IWork
      where S : People,IWork 
{
   return null;
}

//可以用类型参数约束
public static void Show(T tParameter,S sParameter)
      where T : People,ISports
      where S : T
{
   return null;
}

五、泛型的协变,逆变

//所谓协变逆变都是跟泛型相关
//只能放在接口或者委托的泛型参数前面
// out 协变 修饰返回值。就是让右边可以用子类
// out修饰之后只能做返回值,不能做参数
// in 逆变 修饰传入参数
image.png
image.png

你可能感兴趣的:(泛型generic使用和原理)