如何Java的使用现场方差比较C#的声明站点变化?

我的理解是,在C#中指定方差仿制药发生在类型声明级​​别:当你创建你的泛型类型,指定方差的类型参数。 在Java中,在另一方面,方差规定,其中一个通用的方法有:当您创建一些通用类型的变量,您可以指定它的类型参数可以不同。

有哪些优点和缺点,每个选项?

--------------解决方案-------------

我只是要回答申报现场,并使用现场方差之间的差异,因为虽然C#和Java泛型的不同在其他许多方面,这些分歧大多是正交的差异。

首先,如果我没记错的使用现场方差严格小于报关现场的差异更强大的(虽然在简洁的成本),或者至少是Java的通配符是(这实际上比使用现场方差更强大)。 这增加的功率为语言,其中有状态构建体大量使用,如C#和Java(但Scala中少得多,所以,特别是因为它是标准的列表是不可变的)特别有用。 考虑List<E>IList<E> 因为它具有两个添加E和获得E为方法,它是不变的相对于E等声明现场方差不能使用。 然而,随着使用现场方差你可以说List<+Number>获得的协变集ListList<-Number>获得的逆变子集List 。 在声明中,网站的语言库的设计者将不得不作出独立的接口(或者类,如果您允许多重继承的类),每个子集,并具有List扩展这些接口。 如果库设计者没有做到这一点(请注意,C#的IEnumerable只做的协变部分的一小部分IList ),那么你的运气了,你必须求助于你必须做的一门语言不相同的麻烦任何类型的变异。

所以这是使用现场继承的优势声明站点继承。 声明站点继承过度使用现场继承其优点是基本上是简洁的用户(提供设计者通过分离每一个类/接口到它的协变性和逆变部分的精力去)。 对于类似IEnumerableIterator ,这是很好不是必须指定的协方差使用界面的每一个时间。 Java的使用冗长的语法(除bivariance为其Java的解决方案基本上是理想的),使这个最令人讨厌。

当然,这两种语言的特点是可以共存的。 对于类型参数自然协变或逆变(如IEnumerable / Iterator ),在声明中宣布左右。 对于类型参数自然是不变的(例如在(I)List ),宣布什么样的变化,你希望每次使用的时间。 只是不指定使用现场方差与报关现场方差论据,只是使事情变得扑朔迷离。

还有我还没有到其他更详细的问题(比如如何使用通配符实际上比使用现场方差更强大的),但我希望这回答了你的问题,你的内容。 我承认我是偏向使用现场方差,但我试图把双方在我跟程序员和语言研究者的讨论上来的一大优势。

大多数人似乎更喜欢声明站点变化,因为它更容易为图书馆用户 (同时使它有点难为图书馆开发人员,但我认为,图书馆开发者需要考虑差异无论在哪里方差实际上写的。)

但请记住,既不Java和C#是好的语言设计实例。

Java有差异的权利,是因为在Java 5兼容虚拟机的改进和类型擦除JVM的独立工作,利用现场的差异使得使用有点麻烦和具体的实施类型擦除引起了当之无愧的批评。

C#的模型申报现场方差需要负担远离图书馆的用户,但他们的具体化引入泛型的过程中,他们基本建成方差规则到他们的虚拟机。 即使在今天,他们不能完全支持,因为这个错误的合作/逆变(和非向后兼容的引入物化集合类已经分裂程序员分为两大阵营)。

这对瞄准CLR的所有语言困难的限制,是原因之一替代编程语言在JVM上更为活泼,虽然它似乎是CLR已经“好多了功能”。

让我们来看看Scala的 :Scala是一个完全面向对象的,运行在JVM上的功能的混合体。 他们利用类型擦除像Java,但是泛型双方的执行和(声明现场)差异更容易理解,比Java(或C#的)更直接而有力,因为虚拟机并没有对如何变化有规则工作。 Scala编译器检查的变异形式,而可以在编译时 ,而不是在运行时抛出异常拒绝不合理的源代码,而生成的.class文件可以无缝地从Java中使用。

的声明站点方差一个缺点是,它似乎使类型推断更难在某些情况下。

同时斯卡拉可以使用原始的类型,而用拳击他们集合像在@specialized注解告诉Scala编译器生成专门的要求基本类型的类或方法的一个或多个额外的实现。

斯卡拉也“差不多”通过舱单,使它们能够获取泛型类型在运行时就像在C#泛型具体化。

Java的泛型风格的缺点

一个结果是,Java版本只适用于引用类型(或装箱值类型),而不是值类型。 国际海事组织这是最大的缺点,因为它可以防止高性能的仿制药在很多场景和需要的特定类型的手工书写。

它并不能保证一个不变的,如“这份名单只包含类型X的对象”,需要运行时检查在每一个吸气。 通用型确实存在。

当使用反射你不能要求它具有泛型参数的通用对象的实例。

Java的泛型风格优势

你得到的方差/可不同一般参数之间进行转换。

Java的:因为Java 5的破碎协阵列,因为1.0不同的语法使用现场方差仿制药。 没有运行时类型泛型的信息。

C#中:因为C#2.0中使用现场方差仿制药。 新增申报网站差异在C#4.0。 由于1.0(相同的问题,去渣)破碎协阵列,不同的语法。 “具体化”泛型意味着该类型的信息是不是在编译时丢失。

斯卡拉:由于语言(至少自2008年)的早期版本中两者都使用现场/报关现场的差异。 数组是不是一个独立的语言功能,使您在使用相同的泛型的语法和类型的变化规律。 某些集合在虚拟机级使用JVM阵列,以便您的Java代码相比,获得同等或更好的运行时性能来实现。

为了详细说明在C#/ Java数组类型的安全问题:你可以放个狗[]到宠物[],并添加一个猫,并引发未捕获在编译时运行时错误。 斯卡拉正确实现这一点。

分类:C# 时间:2015-03-15 人气:0
分享到:

相关文章

Copyright (C) 55228885.com, All Rights Reserved.

55228885 版权所有 京ICP备15002868号

processed in 1.841 (s). 10 q(s)