草庐IT

c# - 什么是物化?

coder 2023-07-06 原文

我知道 Java 实现了带有删除的参数多态性(泛型)。我明白什么是删除。

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

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

或者您可以在运行时知道某些参数化类型的类型参数是什么,但我不明白它是什么。
  • 什么是具体化类型?
  • 什么是物化值?
  • 当类型/值被具体化时会发生什么?
  • 最佳答案

    具体化是将抽象的事物创造为具体事物的过程。

    C#泛型中的术语具体化是指generic type definition的过程。和一个或多个泛型类型参数(抽象的东西)组合起来创建一个新的泛型类型(具体的东西)。

    换种说法,就是取List<T>定义的过程。和 int并生产混凝土 List<int>类型。

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

  • 在 Java 泛型中,泛型类型定义本质上被转换为一种在所有允许的类型参数组合中共享的具体泛型类型。因此,多个(源代码级别)类型被映射到一个(二进制级别)类型 - 但结果是 information about the type arguments of an instance is discarded in that instance (type erasure) .
  • 作为这种实现技术的一个副作用, native 允许的唯一泛型类型参数是那些可以共享其具体类型的二进制代码的类型;这意味着那些存储位置具有可互换表示的类型;这意味着引用类型。 Using value types as generic type arguments requires boxing them (将它们放在一个简单的引用类型包装器中)。
  • 没有重复的代码以这种方式实现泛型。
  • 可能在运行时(使用反射)可用的类型信息丢失了。反过来,这意味着泛型类型的特化(对任何特定泛型参数组合使用特化源代码的能力)是非常受限的。
  • 这种机制不需要运行时环境的支持。
  • 有几个workarounds to retain type information Java 程序或基于 JVM 的语言可以使用。
  • 在 C# 泛型中,泛型类型定义在运行时在内存中维护。每当需要新的具体类型时,运行时环境都会将泛型类型定义和类型参数结合起来,并创建新类型(具体化)。因此,我们在运行时为类型参数的每个组合获得一个新类型。
  • 这种实现技术允许实例化任何类型的参数组合。使用值类型作为泛型类型参数不会导致装箱,因为这些类型有自己的实现。 ( Boxing still exists in C# ,当然 - 但它发生在其他情况下,而不是这种情况。)
  • 代码重复可能是一个问题 - 但实际上并非如此,因为足够智能的实现( this includes Microsoft .NETMono )可以共享某些实例化的代码。
  • 通过使用反射检查类型参数来维护类型信息,这允许在一定程度上进行特化。然而,特化的程度是有限的,因为泛型类型定义在任何具体化发生之前编译(这是由 compiling the definition against the constraints on the type parameters 完成的 - 因此, the compiler has to be able "understand" the definition even in the absence of specific type arguments )。
  • 这种实现技术在很大程度上依赖于运行时支持和 JIT 编译(这就是为什么您经常听到 C# generics have some limitations on platforms like iOS ,其中动态代码生成受到限制)。
  • 在 C# 泛型的上下文中,具体化是由运行时环境为您完成的。但是,如果您想更直观地理解泛型类型定义和具体泛型类型之间的区别,you can always perform a reification on your own, using the System.Type class (即使您正在实例化的特定泛型类型参数组合没有直接出现在您的源代码中)。
  • 在 C++ 模板中,模板定义在编译时保存在内存中。每当源代码中需要模板类型的新实例化时,编译器就会组合模板定义和模板参数并创建新类型。因此,我们在编译时为模板参数的每个组合获得了一个唯一的类型。
  • 这种实现技术允许实例化任何类型的参数组合。
  • 众所周知,这会复制二进制代码,但足够智能的工具链仍然可以检测到这一点并为某些实例共享代码。
  • 模板定义本身没有“编译” - only its concrete instantiations are actually compiled .这对编译器的约束更少,并允许更大程度的 template specialization .
  • 由于模板实例化是在编译时执行的,这里也不需要运行时支持。
  • 这个过程最近被称为 monomorphization ,尤其是在 Rust 社区。该词与 parametric polymorphism 形成对比。 ,这是泛型来自的概念的名称。
  • 关于c# - 什么是物化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31876372/

    有关c# - 什么是物化?的更多相关文章

    1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

      类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

    2. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

      我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

    3. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

      我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

    4. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

      我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

    5. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

      为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

    6. ruby - ruby 中的 TOPLEVEL_BINDING 是什么? - 2

      它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput

    7. ruby - Infinity 和 NaN 的类型是什么? - 2

      我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串

    8. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

      如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

    9. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

      关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

    10. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

      我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

    随机推荐