Scala 泛型与 C# 的比较

Posted

技术标签:

【中文标题】Scala 泛型与 C# 的比较【英文标题】:Scala generics in comparison to C# 【发布时间】:2010-11-03 01:09:38 【问题描述】:

我只是想知道 Scala 泛型的实现细节。在 C# 中,可以将一个类声明为:

class Foo<T1>
class Foo<T1, T2>

然而,在 Scala 中,同样的事情必须声明为

class Foo0[T1]
class Foo1[T1, T2]

请注意如何为多个泛型参数强制更改类名。 Scala 决定走这条路而不是我觉得更优雅的 C# 是否有原因?我知道这可能是一个很小的挑剔,但我很好奇其中的原因。

【问题讨论】:

只是为了记录,那些在Scala中是不需要的。 【参考方案1】:

我知道 Jon Skeet 的回答已被接受,但它并不完全正确。与其说是 JVM,不如说是 Java 语言强制限制。 Scala 的设计目标是尽可能容易地从 Java 调用,而 Java 没有基于类型参数数量重载类名的概念。例如,在 JVM 上实现基于类型参数的重载的一种简单方法是使用名称修饰。但是,名称修改必须对 Java 可见,并且会很丑陋。在您的示例中,假设的 Scala 可能会编译两个类,Foo_$1 和 Foo_$2。 Scala 可以使这种修改不可见。但是,Java 程序员会看到所有这些丑陋的东西。

【讨论】:

我很确定这就是 C# 所做的。 Foo 的类型名称将是 Foo`1。【参考方案2】:

这很可能部分是由于 Java 的类似限制。据我了解,Scala 主要在 JVM 上使用,您不能通过 arity 重载泛型类型。

它的泛型看起来也像 Scala uses type erasure,即使在 .NET 端口中也是如此。 (同一篇文章提到 Scala 在 Java 真正做到之前很久就有泛型,所以即使 Java 确实 支持这一点,也不能保证 Scala 会 - 他们在第一次设计该功能时受到了一些限制。)

【讨论】:

类型擦除不只是一个聪明的(或多或少)黑客以避免对 JVM 的攻击吗?如果是这样,Scala 是否不需要对 JVM 进行相同的更改以在运行时支持泛型?我宁愿认为 Scala 在这方面并不比 Java 好多少。 除非它在每个实例中添加一些类型信息作为隐藏字段,或者类似的东西。向不支持它们的运行时添加诸如“适当的”泛型之类的东西当然非常困难。 请注意,与 .NET 不同,Scala 泛型可以是更高的种类。我不知道如何在不擦除的情况下将它们添加到 .NET 中。 @alexey_r:很公平——我对 Scala 了解的不够多。是否可以在必要时对高级泛型使用擦除,但对“简单”泛型不使用擦除? 您当然可以通过发明自己的类名修饰方案来创建一种基于 JVM 上的类型参数 arity 重载的语言(非常类似于 C++ 对函数/方法类型和 arity 的重载)。但这将否定 Java 集成曾经很重要的领域。此外,鉴于 ML 派生和 Haskell 的大多数实现在运行时擦除所有类型,我看不出擦除有多“不正确”。【参考方案3】:

我想这样做是为了更容易映射到具有相同限制的 Java。

本来可以进行一些名称修改,但代价是与 Java 的互操作更加困难。在我看来,他们做出了正确的决定。

【讨论】:

以上是关于Scala 泛型与 C# 的比较的主要内容,如果未能解决你的问题,请参考以下文章

泛型与普通方法Object方法效率比较

将泛型与可能是值或引用类型的 null 进行比较?

java泛型与object的比较

Scala入门到精通——第十六节 泛型与注解

C# 中的泛型与非泛型性能

Scala中泛型类型之间的比较