Java 和 C# 中的基本类型有何不同?
我正在手动将代码从 Java 转换为 C#,并与(我所说的)原始类型作斗争(参见,例如 自动装箱和拆箱在 Java 和 C# 中的行为是否不同)。从答案中我了解到 double (C#) 和 Double (C#) 是等效的,并且 double (C#) 也可以在容器中使用,例如作为字典中的键。然而,double
(Java) 不能在像 HashMap 这样的容器中使用,这就是它被自动装箱为 Double
(Java) 的原因。
double
(C#) 是基元还是对象?- 如果它是一个原语,那么它的行为与 double (Java) 不同吗?
double
(C#) 不能设置为 null,除非将其设置为可为 null
。
double?
(C#) 是否等同于Double
(Java)?它们都被称为对象吗?
(在本次讨论中使用术语“一流对象”有用吗?)
I am manually converting code from Java to C# and struggling with (what I call) primitive types (see, e.g. Do autoboxing and unboxing behave differently in Java and C#). From the answers I understand that double
(C#) and Double
(C#) are equivalent and double
(C#) can also be used in containers, e.g. as a key in a Dictionary. However, double
(Java) cannot be used in containers like HashMap which is why it is auto-boxed to Double
(Java).
- Is
double
(C#) a primitive or an object? - If it's a primitive what makes it behave differently from
double
(Java)?
double
(C#) cannot be set to null unless it is made nullable
.
- Is
double?
(C#) equivalent toDouble
(Java)? Are they both referred to as objects?
(Is the use of the term "first-class object" useful in this discussion?)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
C# 和 Java 都有原始(或“值”)类型:int、double、float 等...
但是,在此之后 C# 和 Java 趋于分裂。
Java 为所有基本类型(Java 中的一个小型有限集)提供了包装类类型,这允许将它们视为对象。
double/Double
、int/Integer
、bool/Boolean
等。这些包装类型是引用类型(读作:类),并且,如这样,null
是分配给此类类型表达式/变量的有效值。 Java 的最新版本(1.5/5+)添加了从原语到其相应包装器的隐式强制转换。C# 不提供这样的直接包装1 - 部分原因是 C# 通过 结构;相反,C# 通过引入
Nullable< 来处理“可空值类型”。 T>
包装类型。此外,与 Java 一样,C# 具有从值类型T
到Nullable
的隐式转换,但限制是 T 本身“不是可为 null 的类型”。请注意,
Nullable
也是一种值类型,因此遵循关于值何时/是否“在堆栈上”的标准结构规则。回应评论:
绝对正确,Nullable 作为值类型确实允许它在某些情况下拥有更紧凑的内存占用,因为它可以避免引用类型: Nullable 的内存占用是多少< /a>.然而,它仍然比非 Nullable 类型需要更多的内存,因为它必须记住该值是否为 null。根据对齐问题和 VM 实现,这可能会或可能不会显着小于“完整”对象。此外,由于 C#/CLR 中的值已具体化,因此请考虑必须执行的任何提升操作:
文章 Java 技巧 130:你知道你的数据大小吗? 谈论引用类型内存消耗(在 Java 中)。需要注意的一件事是,JVM 内部有专门的数组版本,每个基本类型和对象都有一个版本(但是,请注意,本文包含一些误导性陈述)。请注意对象(相对于基元)如何产生额外的内存开销和字节对齐问题。然而,C# 可以扩展
Nullable
类型的优化数组情况,而不是 JVM 具有的有限特殊情况,因为Nullable
本身只是一个结构类型(或“原始”)。然而,一个对象只需要一个小的固定大小来在变量槽中维护对其的“引用”。另一方面,
Nullable
类型的变量槽必须具有用于LargeStruct+Nullable
的空间(槽本身可能位于堆上)。请参阅 C# 概念:值与引用类型。请注意,在上面的“提升”示例中,变量的类型为object
:object
是 C# 中的“根类型”(引用类型和值类型的父级),并且不是特殊的值类型。1 C# 语言支持原始/常见类型的一组固定别名,允许访问“友好的小写”类型名称。例如,
double
是System.Double
的别名,int
是System.Int32
的别名。除非在作用域中导入不同的Double
类型,否则double
和Double
将在 C# 中引用相同的类型。我建议使用别名,除非有理由不这样做。Both C# and Java have primitive (or "value") types: int, double, float, etc...
However, after this C# and Java tend to divide.
Java has wrapper Class types for all of the primitive types (which is a small finite set in Java) which allows them to be treated as Object.
double/Double
,int/Integer
,bool/Boolean
, etc. These wrapper types are reference-types (read: Classes) and, as such,null
is a valid value to assign to such typed expressions/variables. Recent versions of Java (1.5/5+) add in implicit coercions from primitives to their corresponding wrapper.C# doesn't provide a such a direct wrapping1 - in part, because C# supports an infinite set of value types via structures; rather, C# handles "nullable value types" by introduction of a
Nullable<T>
wrapper type. In addition C#, like Java, has implicit conversions from the value typeT
toNullable<T>
, with the restriction that T is "not a nullable type" itself.Note that
Nullable<T>
is also a value type and thus follows the standard structure rules for when/if a value is "on the stack" or not.In response to the comment:
Absolutely correct, Nullable being a value-type does allow it to have a more compact memory footprint in certain cases as it can avoid the memory overhead of a reference type: What is the memory footprint of a Nullable<T>. However it still requires more memory than the non-Nullable type because it has to remember if the value is, well, null, or not. Depending upon alignment issues and VM implementation, this may or may not be significantly less than a "full" object. Also, since values in C#/CLR are reified, consider any lifting operations that must be performed:
The article Java Tip 130: Do you know your data size? talks about reference type memory consumption (in Java). One thing to note is that the JVM has specialized versions of Arrays internally, one for each primitive type and for Objects (however, please note that this article contains some misleading statements). Note how the Objects (vs. primitives) incur extra memory overhead and the byte alignment issues. C# however, can extend the optimized-array case for
Nullable<T>
types vs. the the limited special-cases the JVM has becauseNullable<T>
is itself just a structure type (or "primitive").However, an Object, only requires a small fixed size to maintain a "reference" to it in a variable slot. A variable slot of type
Nullable<LargeStruct>
on the other hand, must have space forLargeStruct+Nullable
(the slot itself may be on the heap). See C# Concepts: Value vs Reference Types. Note how in the "lifting" example above the variable is of typeobject
:object
is the "root type" in C# (parent of both reference types and value types) and not a specialized value type.1 The C# language supports a fixed set of aliases for primitive/common types that allow access to "friendly lowercase" type names. For instance,
double
is an alias forSystem.Double
andint
is an alias forSystem.Int32
. Unless a differentDouble
type is imported in scope,double
andDouble
will refer to the same type in C#. I recommend using the aliases unless there is a reason to do otherwise.C# 中的
Nullable
(又名double?
)与 Java 中的Double
不同。在 Java 具有自动装箱/拆箱功能之前,您必须手动在基元和一等对象之间进行转换:
在 Java 1.5 中发生了变化,因此您可以这样做:
并且 Java 会自动插入代码来镜像上述示例。
C# 是不同的,因为有无限数量的“原始”类型(CLR 称之为 值类型)。它们的行为大多类似于 Java 的原语,使用值语义。您可以使用
struct
关键字创建新的值类型。 C# 具有针对所有值类型的自动装箱/拆箱功能,并且还使所有值类型都派生自Object
。因此,您可以使用值类型(如 double ),在其中您可以使用任何对象引用(例如作为字典中的键),并且如有必要,它将被装箱,或者否则就直接使用。 (C# 的泛型实现足以在大多数情况下避免装箱。)
Nullable<double>
(akadouble?
) in C# is not the same as aDouble
in Java.Before Java had autoboxing/unboxing, you had to manually convert between primitives and first-class objects:
In Java 1.5 that changed, so you could just do:
And Java would insert code to mirror the above example automatically.
C# is different because there is an unlimited number of "primitive" types (what the CLR calls value types). These behave mostly like Java's primitives, using value semantics. You can create new value types using the
struct
keyword. C# has autoboxing/unboxing for all value types, and also makes all value types derive fromObject
.So you can use a value type (like
double
) where you would use any object reference (e.g. as a key in aDictionary
) and it will be boxed if necessary, or else just used directly. (C#'s Generics implementation is good enough to avoid boxing in most circumstances.)在 C# 中,分隔对象的最佳方法是通过“值类型”,它有点像基元 -
int
、bool
等,以及“引用类型” - 类等。In C#, the best way to separate objects are by "Value Types" which are kinda like primitives -
int
s,bool
s, etc and "Reference Types" - classes etc.