简单的问题——为什么 Decimal 类型定义这些常量? 为什么要这么麻烦?
我正在寻找一个原因,为什么这是由语言定义的,不可能的使用或对编译器的影响。为什么一开始要把这个放进去?编译器可以像处理 Decimal 一样轻松地内联0m。零,所以我不认为它是编译器的快捷方式。
我的 意见是它们是用来帮助避免魔术数字的。
神奇的数字基本上就是在你的代码中的任何地方,你有一个随处可见的数字。例如:
int i = 32;
这是有问题的,因为没有人能够告诉 为什么i 被设置为32,或者32表示什么,或者它是否应该是32。神奇又神秘。
类似地,我经常看到这样做的代码
int i = 0; int z = -1;
为什么它们被设置为0和 -1? 这只是巧合吗? 它们有什么意义吗? 谁知道呢?
虽然 Decimal.One、 Decimal.Zero等等没有告诉你这些值在你的应用程序中意味着什么(也许零意味着“丢失”等等) ,但是 是的告诉你这些值是有意设置的,并且可能有一些意义。
Decimal.One
Decimal.Zero
虽然不完美,但这总比什么都不告诉你要好得多: -)
注意 它是用于优化的 没有,请观察下面的 C # 代码:
public static Decimal d = 0M; public static Decimal dZero = Decimal.Zero;
当使用 ildasm 查看生成的字节码时,这两个选项都会导致 一模一样MSIL。System.Decimal是一种值类型,所以 Decimal.Zero并不比仅仅使用文字值更“优化”。
System.Decimal
有一些。NET 语言不支持十进制文字,在这种情况下,用 Decimal.ONE 代替 new Decimal (1)更方便(也更快)。
出于同样的原因,Java 的 BigInteger 类也有0和1。
小小的澄清一下。它们实际上是静态的只读值,而不是常量。这两者之间有着明显的区别。因为各种编译器的常量值都是 内嵌的,因此不可能在编译的程序集中跟踪它们的使用情况。然而,静态只读值不会被复制,而是被引用。这对你的问题是有利的,因为这意味着它们的使用可以被分析。
如果您使用反射器并深入挖掘 BCL,您会注意到 MinusOne 和 Zero 只在 VB 运行时中使用。它的存在主要是为了在 Decimal 和 Boolean 值之间进行转换。为什么 MinusOne 在今天(链接)碰巧出现在一个单独的线程上
奇怪的是,如果你看一下十进制,你会发现有一个值没有被使用。
至于为什么他们被明确定义... 我怀疑有一个硬和快速的原因。有 出现了没有具体的性能,只有一点方便的措施,可以归因于他们的存在。我的 猜猜看是,他们是由某人在开发的 BCL 的方便,只是从来没有删除添加。
剪辑
在@Paleta 的评论之后,我们深入挖掘了一下 const的问题。Decimal.One的 C # 定义使用 const修饰符,但是它在 IL 级别作为 static readonly发出。C # 编译器使用了一些技巧,使这个值与 const(例如内联字面值)几乎无法区分。这将显示在识别这种技巧的语言中(VB.Net 识别这种技巧,但 F # 不识别)。
const
static readonly
这三个数值啊! ! !
我认为它们可能与我所说的 跟在1后面有关
假设你有这个公式:
(x)1.116666 + (y) = (z)2.00000
但是 X,Z被四舍五入到 0.11和 2.00,并且你被要求计算(y)。
所以你可能认为 y = 2.00 - 1.11。实际上 嘿等于 0.88,但是你会得到 0.89。(有一个 0.01的差异)。
y = 2.00 - 1.11
取决于 x 和 y 的实际值,结果从 -0.01到 + 0.01会有所不同,在某些情况下,当处理一大堆跟随1的时候,为了方便起见,你可以检查跟随值是否等于 Decimal.MinusOne / 100,Decimal.One / 100或者 Decimal.Zero / 100来修正它们。
Decimal.MinusOne / 100
Decimal.One / 100
Decimal.Zero / 100
我就是这样利用他们的。