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