C#和Java都有原始(或“值”)类型:int,double,float等。
但是,在此之后,C#和Java往往会分开。
Java为所有基元类型(这是Java中的一个小有限集)提供了包装器类类型,这允许将它们视为对象。等。这些包装器类型是引用类型(读取:类),因此是分配给此类类型化表达式/变量的有效值。最新版本的Java(1.5 / 5 +)添加了从基元到其相应包装器的隐式强制。double/Double
int/Integer
bool/Boolean
null
// Java
Boolean b = true; // implicit conversion boolean -> Boolean (Java 5+)
Boolean b = null; // okay, can assign null to a reference type
boolean n = null; // WRONG - null is not a boolean!
C#不提供这样的直接包装1 - 部分原因是C#通过结构支持无限的值类型集;相反,C# 通过引入 Nullable<T> 包装器类型来处理“可为 null 的值
类型”。此外,与 Java 一样,C# 具有从值类型到 的隐式转换,但限制 T 本身“不是可为 null 的类型”。T
Nullable<T>
// C#
Nullable<bool> b = true; // implicit conversion bool -> bool?
bool? b = true; // short type syntax, implicit conversion
bool? b = null; // okay, can assign null as a Nullable-type
bool b = null; // WRONG - null is not a bool
请注意,这也是一种值类型,因此遵循有关值何时/是否“在堆栈上”的标准结构规则。Nullable<T>
针对评论:
绝对正确,Nullable是一种值类型,在某些情况下确实允许它具有更紧凑的内存占用量,因为它可以避免引用类型的内存开销:Nullable<T>的内存占用量是多少。但是,它仍然需要比不可 Null 类型更多的内存,因为它必须记住该值是否为 null。根据对齐问题和 VM 实现,这可能明显小于“完整”对象,也可能不明显小于“完整”对象。此外,由于 C#/CLR 中的值已重新确定,因此请考虑必须执行的任何提升操作:
// C#
object x = null;
x = (bool?)true;
(x as bool?).Value // true
文章 Java 提示 130:您知道您的数据大小吗?讨论了引用类型的内存消耗(在 Java 中)。需要注意的一点是,JVM 内部有专门的 Arrays 版本,每个基元类型和对象都有一个(但是,请注意,本文包含一些误导性陈述)。请注意对象(与基元相比)如何产生额外的内存开销和字节对齐问题。但是,C#可以扩展类型的优化数组情况,而不是JVM的有限特殊情况,因为本身只是一种结构类型(或“原语”)。Nullable<T>
Nullable<T>
但是,对象只需要很小的固定大小即可在可变槽中保持对它的“引用”。另一方面,类型的可变插槽必须具有空间(插槽本身可能在堆上)。请参见 C# 概念:值与引用类型。请注意,在上面的“提升”示例中,变量的类型为:是 C# 中的“根类型”(引用类型和值类型的父级),而不是专用值类型。Nullable<LargeStruct>
LargeStruct+Nullable
object
object
1 C# 语言支持一组固定的基元/公共类型的别名,这些别名允许访问“友好小写”类型名称。例如,是 的别名,并且是 的别名。除非在作用域中导入了不同的类型,并且将在 C# 中引用相同的类型。我建议使用别名,除非有理由这样做。double
System.Double
int
System.Int32
Double
double
Double