我知道Java通过擦除实现参数多态性(泛型)。我明白了什么是删除。
我知道 C# 通过具体化实现参数多态性。我知道这可以让你写作
public void dosomething(List<String> input) {}
public void dosomething(List<Int> input) {}
或者您可以在运行时知道某些参数化类型的类型参数是什么,但我不明白它是什么is.
- 什么是具体化类型?
- 什么是具体化价值?
- 当类型/值具体化时会发生什么?
具体化是把抽象事物创造为具体事物的过程。
期限具体化在 C# 中,泛型是指一个过程泛型类型定义以及一个或多个泛型类型参数(抽象的东西)组合起来创造一个新的泛型(具体的事情)。
换句话说,这是获取定义的过程List<T>
and int
并生产混凝土List<int>
type.
要进一步理解它,请比较以下方法:
-
在 Java 泛型中,泛型类型定义本质上被转换为在所有允许的类型参数组合之间共享的一种具体泛型类型。因此,多种(源代码级别)类型被映射到一种(二进制级别)类型 - 但结果是,有关实例类型参数的信息在该实例中被丢弃(类型擦除).
- 作为这种实现技术的副作用,本机允许的唯一泛型类型参数是那些可以共享其具体类型的二进制代码的类型;这意味着那些存储位置具有可互换表示形式的类型;这意味着引用类型。使用值类型作为泛型类型参数需要将它们装箱(将它们放在一个简单的引用类型包装器中)。
- 为了以这种方式实现泛型,不需要重复任何代码。
- 在运行时(使用反射)可用的类型信息丢失了。反过来,这意味着泛型类型的专门化(使用专门化的能力)源代码对于任何特定的通用参数组合)是非常有限的。
- 该机制不需要运行时环境的支持。
- 有几个保留类型信息的解决方法Java 程序或基于 JVM 的语言可以使用。
-
在 C# 泛型中,泛型类型定义在运行时维护在内存中。每当需要新的具体类型时,运行时环境就会组合泛型类型定义和类型参数并创建新类型(具体化)。所以我们为类型参数的每个组合得到一个新类型,在运行时.
- 这种实现技术允许实例化任何类型的类型参数组合。使用值类型作为泛型类型参数不会导致装箱,因为这些类型有自己的实现。 (拳击在 C# 中仍然存在,当然 - 但它发生在其他场景中,而不是这个场景。)
- 代码重复可能是一个问题 - 但实际上并不是,因为足够智能的实现(这包括 Microsoft .NET and Mono)可以共享某些实例化的代码。
- 通过使用反射检查类型参数,可以维护类型信息,从而在一定程度上允许专业化。然而,由于泛型类型定义是编译的,所以专业化程度是有限的before任何具体化都会发生(这是通过根据类型参数的约束编译定义- 因此,即使没有特定类型参数,编译器也必须能够“理解”定义).
- 这种实现技术在很大程度上依赖于运行时支持和 JIT 编译(这就是为什么您经常听到这样的说法)C# 泛型在 iOS 等平台上有一些限制,其中动态代码生成受到限制)。
- 在 C# 泛型的上下文中,具体化是由运行时环境为您完成的。但是,如果您想更直观地了解泛型类型定义和具体泛型类型之间的区别,你总是可以自己执行具体化,使用System.Type class(即使您正在实例化的特定泛型类型参数组合没有直接出现在源代码中)。
-
在 C++ 模板中,模板定义在编译时保存在内存中。每当源代码中需要模板类型的新实例化时,编译器就会组合模板定义和模板参数并创建新类型。因此,我们为模板参数的每个组合获得一个唯一的类型,在编译时.
- 这种实现技术允许实例化任何类型的类型参数组合。
- 众所周知,这会重复二进制代码,但足够智能的工具链仍然可以检测到这一点并共享某些实例化的代码。
- 模板定义本身没有“编译” -实际上只编译它的具体实例。这对编译器的限制更少,并且允许更大程度的模板专业化.
- 由于模板实例化是在编译时执行的,因此这里也不需要运行时支持。
- 这个过程最近被称为单态化,尤其是在 Rust 社区。这个词是用来对比的参数多态性,这是泛型的概念名称。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)