• 运行时中的泛型


    当泛型类或泛型方法被编译为微软中间语言(MSIL)后,它所包含的元数据定义了它的类型参数。根据所给的类型参数是值类型还是引用类型,对泛型类型所用的MSIL也是不同的。

        当第一次以值类型作为参数来构造一个泛型类型,运行时用所提供的参数或在MSIL中适当位置被替换的参数,来创建一个专用的泛型类型。[JX3] 

     

        例如,假设你的程序代码声名一个由整型构成的栈,如:

    Stack<int> stack;

    此时,运行时用整型恰当地替换了它的类型参数,生成一个专用版本的栈。此后,程序代码再用到整型栈时,运行时复用已创建的专用的栈。下面的例子创建了两个整型栈的实例,它们共用一个Stack<int>代码实例:

    Stack<int> stackOne = new Stack<int>();
    Stack<int> stackTwo = new Stack<int>();

        然而,如果由另一种值类型——如长整型或用户自定义的结构——作为参数,在代码的其他地方创建另一个栈,那么运行时会生成另一个版本的泛型类型。这次是把长整型替换到MSIL中的适当的位置。由于每个专用泛型类原本就包含值类型,因此不需要再转换。

     

        对于引用类型,泛型的工作略有不同。当第一次用任何引用类型构造泛型类时,运行时在MSIL中创建一个专用泛型类,其中的参数被对象引用所替换。之后,每当用一个引用类型作为参数来实例化一个已构造类型时,就忽略其类型,运行时复用先前创建的专用版本的泛型类。这可能是由于所有的引用的大小都相同。

     

        例如,假如你有两个引用类型,一个Customer类和一个Order类;进一步假设你创建了一个Customer的栈:

    Stack<Customer> customers;

    此时,运行时生成一个专用版本的栈,用于稍后存储对象的引用,而不是存储数据。假如下一行代码创建了一个另一种引用类型的栈,名为Order:

    Stack<Order> orders = new Stack<Order>();

     和值类型不同,运行时并没有为Order类型创建另一个栈的专用版本。相反,运行时创建了一个专用版本栈实例,并且变量orders指向这个实例。如果之后是一行创建Customer类型的栈的代码:

     

    customers = new Stack<Customer>();

    和之前以Order类型创建的栈一样,创建了专用栈的另一个实例,并且其中所包含的指针指向一块大小与Customer类一致的内存。由于不同程序间引用类型的数量差别很大,而编译器只为引用类型的泛型类创建一个专用类,因此C#对泛型的实现极大地降低了代码膨胀。

    此外,当用类型参数实现一个泛型C#类时,想知道它是指类型还是引用类型,可以在运行时通过反射确定它的真实类型和它的类型参数。

  • 相关阅读:
    2019-4-16-C#-使用反射获取私有属性的方法
    2019-5-21-C#-命令行如何静默调用-del-删除文件
    2019-6-14-WPF-shows-that-some-windows-in-multithreading-will-be-locked-in-the-PenThreadWorker-constr...
    2019-9-11-完整的-P2P-应用需要包含哪些功能
    2019-3-1-VisualStudio-扩展开发-获得输出窗口内容
    2018-10-19-C#-序列类为-xml-可以使用的特性大全
    2018-8-10-win10-uwp-手把手教你使用-asp-dotnet-core-做-cs-程序
    2018-10-31-win10-uwp-使用-asp-dotnet-core-做图床服务器客户端
    2018-8-10-docfx-做一个和微软一样的文档平台
    linux分区方案
  • 原文地址:https://www.cnblogs.com/XiaoRuLiang/p/12422319.html
Copyright © 2020-2023  润新知