为什么十进制不是原始类型?

21

为什么decimal不是原始类型?

Console.WriteLine(typeof(decimal).IsPrimitive);

输出结果为false

decimal是一种基础类型,它是语言规范的一部分,但不是原始类型。在框架中,哪些原始类型代表了decimal?例如,int有一个类型为intm_value字段。而double有一个类型为doublem_value字段。但对于decimal来说,情况并非如此。它似乎由一堆int表示,但我不确定。

为什么decimal看起来像原始类型,行为类似于原始类型(除了少数情况),但实际上不是原始类型呢?

3个回答

24

虽然不是一个直接的答案,但IsPrimitive的文档列出了原始类型:

http://msdn.microsoft.com/en-us/library/system.type.isprimitive.aspx

这里有一个类似的问题:

http://bytes.com/topic/c-sharp/answers/233001-typeof-decimal-isprimitive-false-bug-feature

Jon Skeet所引用的回答:

CLR不需要有任何关于十进制类型的内在知识——它只把它视为另一种值类型,恰好具有重载运算符。例如,没有直接操作十进制数的IL指令。

对我来说,decimal似乎是语言/运行时想要符合CLS/CLI标准必须存在的一种类型(因此被称为“基元”因为它是具有关键字支持的基类型),但实际实现并不要求它真正成为“基本”类型(因为CLR不认为它是原始数据类型)。


是的,我读了这个链接。虽然我给出的第一个链接是针对VB的,但它将decimal列为原始类型。在VB中尝试我的片段也返回了false。也许VB的规范存在错误(或者已经过时了...)! - Guillaume
2
@Guillaume 是的,我看到了那个链接,我认为这可能取决于“原始”的定义在哪里。在CLR中,它不是原始类型,但如果您只考虑规范(CLR是其实现之一),则似乎被描述为原始类型。 - Adam Houldsworth
我认为混淆可能在于术语;例如,框架原始类型是一种东西,而.NET支持的语言的“内置”类型则是另一种东西,但在该语言的上下文中以不同的意义被视为“原始”? - Grant Thomas
@GrantThomas 我同意,这也是我最好的猜测,我希望在答案中传达这一点。 - Adam Houldsworth
1
一个更有趣的情况是 string,在我看来应该被视为原始类型,因为它和 Array 是仅有的两种可变大小的类型,并且它的存储方式与 Array 不同。 - supercat
显示剩余2条评论

13

Decimal是一种128位的数据类型,在计算机硬件上无法本地表示。例如,64位计算机体系结构通常具有整数和寻址寄存器,其宽度为64位,可以直接支持64位的数据类型和地址。

维基百科指出:

根据语言及其实现的情况,原始数据类型可能与计算机内存中的对象存在一对一或非一对一的对应关系。然而,人们通常希望在基本原始数据类型上进行的操作是最快速的语言构造。

在十进制的情况下,它只是一个复合数据类型,内部使用整数,因此其性能比直接与计算机内存相关的数据类型(如int、double等)要慢。


我没有考虑到这个数据结构对架构的影响...我会尽量找到更多关于这个的信息。 - Guillaume
4
虽然我理解答案背后的思路,但这个想法是否可以证明适用于在32位系统上宽度为63位的类型,例如doublelong?我的意思是CLR可能不考虑这种原始类型的定义。 - Adam Houldsworth
1
因此,实际上,当我们拥有128位计算机十年后,小数也可以变成基本数据类型。 - RBT

5

考虑下面的例子,

     int i = 5;
    float f = 1.3f;
    decimal d = 10;

如果您放置一个调试器并验证本机指令集,它将是

enter image description here

正如您所看到的,intfloat 都是原始类型,只需单条指令即可执行赋值操作,而 decimal,string 是非原始类型,需要多个本地指令才能执行此操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接