我的理解是,指定差异仿制药C#发生在类型声明的水平:当你们创造你的通用型的,你指定的差异为的类型参数。在爪哇,另一方面,差异是指定一个通用的是用于:在创建一个可变的一些通用的类型,可以指定其类型参数可能有所不同。

什么是每个利弊的选择吗?

有帮助吗?

解决方案

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

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

这就是在报关现场继承的使用现场继承的优势。声明站点继承过度使用现场继承的优点是基本上是为用户(提供设计者通过每一个类/接口分离为其协变和逆变部分的精力去)简洁。对于像IEnumerableIterator,很高兴没有必须指定协方差您使用的接口每一次。爪哇通过使用冗长的语法(除了bivariance针对Java的溶液基本上是理想的)制成此尤其烦人。

当然,这两种语言的特征可以共存。对于类型参数是天然协变或逆变(如在IEnumerable / Iterator),在声明声明如此。对于类型参数自然是不变的(如(I)List),声明一种变异的你想要的每次使用它的时候。只要不指定一个声明站点方差参数的使用现场方差,只是使事情变得扑朔迷离。

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

其他提示

大多数人似乎更喜欢声明站点变化,因为它更容易为用户的库(同时使它有点困难的库开发,虽然我认为库开发有考虑方差无论在哪里方差实际写入的。)

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

虽然的爪哇得到方差右和由于Java 5中兼容VM改进和类型擦除,使用现场方差使得使用有点麻烦和特定的实现类型的JVM的独立工作的-erasure已引起当之无愧批评。

C#的宣言现场方差模型采用的负担从库的用户了,但他们的具体化推出仿制药的过程中,他们基本建成方差规则到他们的虚拟机。 今天他们甚至不能完全支持合作/逆变因为这个错误(与非向后兼容引进物化集合类的已经程序员分成了两个阵营)的。

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

让我们看的 Scala的:Scala是在JVM运行的完全面向对象的,功能性的混合体。 他们利用类型擦除像Java,但仿制药的同时实现和(声明站点)方差更容易理解,不是更简单和强大的Java(或C#的),因为虚拟机没有对变异如何有规则工作。 Scala编译器检查方差符号和可以拒绝不健全的源代码的在编译时的代替在运行时抛出异常,而生成的.class可以无缝地从Java一起使用的文件。

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

同时Scala中可以通过使用@specialized注解它告诉Scala编译器使用原始的类型,而在C#拳击它们在集合等,从而生成专用于一个类或方法的一个或多个另外的实施方式要求的原始类型。

Scala中也可以在“几乎”通过使用舱单这允许它们检索泛型在运行时像在C#泛型具体化

缺点Java泛型的风格

一个后果是,java version只适用基准类型(或装箱的价值类型)和没有价值类型。海事组织是最大的缺点,因为它可以防止高效仿制药在很多的情况和需要手册的编写专门的类型。

它并不能保证一个不变的像"这个清单只包含对象的类型x"和需要运行检查,在每一个吸气。一般类型确实存在。

当使用的反思,你不能要求的一个实例,一般对象的通用参数。

优点Java泛型的风格

你差/可以投射之间的不同的通用参数。

爪哇:由于具有自1.0不同的语法的Java 5.分拆协变阵列使用现场方差泛型。没有泛型的运行时类型信息。

C#:由于C#2.0使用现场方差泛型。新增申报网站方差在C#4.0。由于1.0(相同问题到Java等)来划分与不同的语法协变阵列。 “具体化”泛型意味着类型信息不是在编译时丢失。

Scala的:由于语言(自2008年至少)的早期版本两者都使用现场/声明现场方差。数组是不是一个独立的语言功能,让你用同样的仿制药的语法和类型的变化规律。某些集合在虚拟机级与JVM阵列实现的,所以你用Java代码相比,获得同等或更好的运行时性能。

要阐述一下C#/ Java数组类型安全问题:您能投射出狗[]对宠物[],并添加一个猫并触发未在编译时捕获运行时错误。阶正确实现这一点。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top