标签00标签01标签02

  • 泛型类型
  • 为什么需要泛型
  • 泛型方法
  • 声明类型参数
  • typeof和未绑定泛型类型
  • 泛型的默认值
  • 泛型的约束
  • 继承泛型类型
  • 自引用泛型声明
  • 类型参数的转换
  • 协变
    • 可变性不是自动的
    • 数组
    • 声明协变类型参数
  • 逆变
  • C#泛型和C++模板对比

:::tips

  • C#有两种不同的机制来编写跨类型可复用的代码继承泛型
  • 继承的复用性来自于基类,泛型的复用性是通过”占位符“的”模板“类型来实现的。
  • 和继承相比,泛型能够提高类型的安全性,并减少类型的转换和装箱。 :::

    泛型类型

    泛型类型中声明的类型参数(占位符类型)需要由泛型类型的消费者(即提供类型参数的一方)填充。=》使用的时候才能够确定泛型中参数对应的数据类型。

    1. //泛型类Stack
    2. //泛型对应的参数T,此时并不知道其具体的参数属于哪一种数据类型
    3. public class Stack<T>
    4. {
    5. private int position;
    6. private T[] data = new T[100];
    7. public void Push(T obj) => data[position++] = obj;
    8. public T Pop() => data[--position];
    9. }

    调用泛型类Stack

    1. private static void Main(string[] args)
    2. {
    3. var stack = new Stack<int>(); //使用的时候,确定泛型参数的数据类型
    4. //根据下标索引到数组并赋值
    5. stack.Push(5); //position++=>1,data[0]=5
    6. stack.Push(10); //position++=>2,data[1]=10
    7. int x = stack.Pop(); //此时position=2,执行--position后=>1,即x=data[1]=10
    8. int y = stack.Pop(); //此时position=1,执行--position后=>0,即y=data[0]=0
    9. }

    其实上面的泛型类Stack就类似于确定了T具体的数据类型

    1. public class StackTemplate
    2. {
    3. private int position;
    4. private int[] data = new int[100];
    5. public void Push(int obj) => data[position++] = obj;
    6. public int Pop() => data[--position];
    7. }

    :::success 温馨提示:

  • 技术上,我们称Stack是开放类型,称Stack为封闭类型。

  • 在运行时,所有的泛型实例都是封闭的,占位符已经被类型填充。这就意味着如下语句是非法的:stack=new Stack<T>();
  • 只有在类或者方法内部,T才可以定义为类型参数:

public class Stack
{

public Stack Clone()
{
Stack clone=new Stack();
}

} :::

为什么需要泛型?

泛型是为了代码能够跨类型复用而设计的。

总结


  • 联系我:GitHub|E-Mail|语雀
  • 作者:Felix Sun | 励志做一名有温度的技术人
  • 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!