2010-11-20 96 views

回答

28

C#有一个统一的类型系统。 所有C#类型,包括原始类型,例如从单个根object型 int和double,继承。与类对象不同,这些基本类型是值类型。它们不是分开堆放,而是按价值传递。

当C#值类型(例如,基元int或用户定义的结构)被放置在一个参数集合,它被存储在与没有指针一个密集阵列。这是可能的,因为C#为每个需要的不同参数“大小”定制参数化实例。这意味着当您实例化C#List<int>时,底层数组列表存储密集打包的int数组。

来源:http://www.pin5i.com/showtopic-24376.html

的Java有几个原始类型(INT,长双,字节,等等) - 但是,他们是特殊的,因为它们是不是面向对象的,他们不能用语言本身来定义。它们是值类型,不是分配堆,而是按值传递。

来源:Comparison of C# and Java - Unified type system(维基百科)

与此同时,Java还具有面向对象的原始的 “包装” 类型(整数,长,双,字节等),通常被称为boxed类型。这些是通过引用传递的堆分配对象,并且与上述基本类型并行存在。

在较新版本的Java,基本类型自动装箱为目标类型时必要的。这减轻了管理它们的大部分负担,但它也可能导致微小的错误(另请参阅auto-boxing)。

相比于C#,Java中,内置的JDK集合框架总是设法对象指针的集合。为了使它们以向后兼容的方式参数化,Java执行了一种称为type-erasure的技术,其中(在运行时)所有内容均被视为容器内的对象(参数化类型检查在编译时执行)。

这意味着,你不能让一个Java List<int>,您只能List<Integer>。而且,上面的列表实际上存储了一个指向盒装Integer对象的指针数组,它的大小是C#版本的两倍,性能也大大降低。对于大多数使用情况,这种尺寸和性能的差异是无关紧要的。

在使用情况下,尺寸和性能是相关的,有两种方法可供选择:

  1. 当你知道你的名单提前大小,使用原生类型的数组,例如int[]。原生类型的数组打包在内存中,因此它们消耗的LOT更少,性能更高。
  2. 当你不知道你的名单提前大小,使用该包装的原生阵列,从而能够创建之后元素添加到它的一些第三方列表实现(一些例子:TroveColtFastutilGuava) 。
+0

我读过一次大学项目,一个编程语言使用统一类型系统,既有基本类型和对象,但基本类型有一个隐藏的继承,基本对象和基本类型,其中的子类一个隐藏的根类型 – umlcat 2011-04-01 17:45:40

+0

哈哈,听起来很熟悉,这个项目发生了什么umlcat lol – brumScouse 2012-05-04 11:52:12

+0

@brumScouse:不知道。我失去了链接。我开始在自定义宠物项目中应用我学到的知识。 Java和C#都不仅是对象编程。我认为它可以拥有原始类型和一个统一的类型系统,它独立于对象定向。 – umlcat 2012-12-31 17:37:06

12

这实际上不是C#的真实情况,并非所有类型都来自对象,就像99.9%的对象一样。有一些非常奇怪的类型不能转化为对象。 唯一正式支持的是指针。 还有3个像TypedReference,RuntimeArgumentHandle这样的不受支持的类,另外还有一个名字让我感到失望。这三种类型与C++/C中的变长方法交互使用。我不会担心他们太多。

+0

这是神经破坏探索这个神话的细节[这里](https://blogs.msdn.microsoft.com/ericlippert/2009/08/06/not-everything-derives-from-object/)你能找出第三种不支持的类型?顺便说一句,即使指针不支持,直到你将它们转换为“System.IntPtr”或“System.UIntPtr”值类型。 – RBT 2016-12-26 05:51:29