小编典典

什么是物化?

all

我知道Java通过擦除实现了参数多态性(泛型)。我明白什么是擦除。

我知道 C# 通过具体化实现了参数多态性。我知道这可以让你写作

public void dosomething(List<String> input) {}
public void dosomething(List<Int> input) {}

或者您可以在运行时知道某些参数化类型的类型参数是什么,但我不明白它 什么。

  • 什么是物化类型?
  • 什么是物化价值?
  • 当类型/值被具体化时会发生什么?

阅读 328

收藏
2022-08-21

共1个答案

小编典典

物化是一个抽象的东西和创造一个具体的东西的过程。

C# 泛型中的术语 具体化 是指将_泛型类型定义_ 和一个或多个 泛型类型参数
(抽象事物)组合以创建新 泛型类型 (具体事物)的过程。

换一种说法,它是定义List<T>int产生具体List<int>类型的过程。

要进一步理解它,请比较以下方法:

  • 在 Java 泛型中,泛型类型定义本质上被转换为一种在所有允许的类型参数组合中共享的具体泛型类型。因此,多个(源代码级别)类型被映射到一个(二进制级别)类型 - 但结果,有关实例类型参数的信息在该实例中被丢弃(类型擦除)

    1. 作为这种实现技术的副作用,本机允许的唯一泛型类型参数是那些可以共享其具体类型的二进制代码的类型;这意味着那些存储位置具有可互换表示的类型;这意味着引用类型。使用值类型作为泛型类型参数需要将它们装箱(将它们放在简单的引用类型包装器中)。
    2. 为了以这种方式实现泛型,无需重复任何代码。
    3. 可能在运行时可用的类型信息(使用反射)丢失了。反过来,这意味着泛型类型的专门化(对任何特定泛型参数组合使用专门的 源代码 的能力)非常有限。
    4. 这种机制不需要运行时环境的支持。
    5. 有一些变通方法可以保留Java 程序或基于 JVM 的语言可以使用的类型信息。
    6. 在 C# 泛型中,泛型类型定义在运行时保存在内存中。每当需要一个新的具体类型时,运行时环境就会结合泛型类型定义和类型参数并创建新类型(具体化)。 因此,我们在运行时 为类型参数的每个组合获得了一个新类型。

    7. 这种实现技术允许实例化任何类型的类型参数组合。使用值类型作为泛型类型参数不会导致装箱,因为这些类型有自己的实现。

    8. 代码重复可能是一个问题——但实际上并非如此,因为足够智能的实现(包括 Microsoft .NETMono)可以为某些实例共享代码。
    9. 通过使用反射检查类型参数来维护类型信息,这允许在一定程度上进行专门化。然而,专业化的程度是有限的,因为泛型类型定义在任何具体化发生 之前 被编译(这是通过根据类型参数的约束编译定义来完成的- 因此,编译器必须能够即使在没有特定类型参数的情况下也能“理解”定义)。
    10. 这种实现技术在很大程度上依赖于运行时支持和 JIT 编译(这就是为什么你经常听到C# 泛型在 iOS 等平台上存在一些限制,其中动态代码生成受到限制)。
    11. 在 C# 泛型的上下文中,具体化由运行时环境为您完成。但是,如果您想更直观地理解泛型类型定义和具体泛型类型之间的区别,您始终可以使用System.Type自行执行具体化(即使您实例化的特定泛型类型参数组合没有’ t 直接出现在您的源代码中)。
    12. 在 C++ 模板中,模板定义在编译时保存在内存中。每当源代码中需要模板类型的新实例时,编译器就会结合模板定义和模板参数并创建新类型。 所以我们在编译时 为模板参数的每个组合获得了一个唯一的类型。

    13. 这种实现技术允许实例化任何类型的类型参数组合。

    14. 众所周知,这会复制二进制代码,但足够智能的工具链仍然可以检测到这一点并为某些实例共享代码。
    15. 模板定义本身不是“编译的”——只有它的具体实例被实际编译。这对编译器的约束更少,并允许更大程度的模板专业化
    16. 由于模板实例化是在编译时执行的,因此这里也不需要运行时支持。
    17. 这个过程最近被称为 单态 化,尤其是在 Rust 社区中。该词用于与参数多态性形成对比, 参数多态性 是泛型来自的概念的名称。
2022-08-21