【问题标题】:Why does assigning an a value greater than an int to an int not throw an exception by default? [duplicate]为什么默认情况下将大于 int 的值分配给 int 不会引发异常? [复制]
【发布时间】:2013-05-17 12:50:48
【问题描述】:

我使用 ILSpy 反映到 LINQ's Sum 方法中,并注意到它只是使用 checked 关键字执行 foreach。但是,如果int 有一个已定义的最大值并且您尝试超过它,为什么默认情况下它不会抛出错误。假设您不使用Sum 并且您自己使用foreach 而没有checked,则不会出现异常,如果您超过最大int 值,它只会给您一个垃圾值,但我看不出这不仅仅是默认行为的原因。如果您需要比int 更大的东西,请不要使用int。

【问题讨论】:

  • 您可以在项目设置中启用检查算法。我几乎所有项目都这样做。
  • @CodesInChaos - 好吧,我从来不知道这一点。感谢您指出这一点,但为什么仍然不是这种默认行为?从我自己的角度来看,如果我知道某个值将超过 int 的最大值,我会使用更大的值。
  • unchecked 有用的一个地方是GetHashCode,int 是否溢出并不重要。它只需要快速且相当准确。如果GetHashCode 返回相同的值,Equals 无论如何都用于确定两个对象是否真的相等。 stackoverflow.com/a/263416/284240
  • @CodesInChaos - 如果你在项目设置中这样做,它是否适用于整数、短裤等?您是否有正当理由要为 int 的算术溢出引发错误,而不是 short?

标签: c# .net


【解决方案1】:

已检查的操作比未检查的要慢得多:

const int startVal = Int32.MaxValue - 1000000;
Stopwatch sw = new Stopwatch();

sw.Start();
int i = startVal;
while (i < Int32.MaxValue)
{
    unchecked
    {
        i++;
    }
}
sw.Stop();
Console.WriteLine("Unchecked: " + sw.ElapsedTicks + " ticks");

i = startVal;
sw.Restart();
while (i < Int32.MaxValue)
{
    checked
    {
        i++;
    }
}
sw.Stop();
Console.WriteLine("Checked: " + sw.ElapsedTicks + " ticks");

结果:

未选中:241 个滴答声
检查:1992 滴答声

所以使用检查会导致性能下降,并且由于溢出相对较少(实际上谁计数到Int32.MaxValue?),C# 默认使用未检查。

【讨论】:

  • 但是因为它在 99% 的代码中都无关紧要,所以最好默认启用它并仅选择性地禁用它。
  • 没想到会这么多?你是根据什么来衡量这些指标的?
  • 感谢您的示例。
  • 发布模式下的标准 .NET 4 控制台应用程序
  • 当然,但是您的代码示例有一个缺点,即在一种情况下会引发异常并由catch 块处理,而在另一种情况下不会浪费时间。也许您应该更改为while (i != int.MaxValue) 并删除try-catch?
【解决方案2】:

我看不出这不仅仅是默认行为的原因

执行此类检查可能会涉及成本 - 检查处理器标志,或(如果在内部使用更大的寄存器)检查寄存器的高位内容。基本分配可能是在最紧密的循环中进行的操作 - 成本可能是可观的,而且不是每个人都应该付费。

因此,您可以选择是否要进行这些检查。

【讨论】:

  • 好吧,有道理,但我不是硬件专家,但随着今天硬件的进步,这真的更重要吗?这可能是一个愚蠢的说法,但就像我说的那样,我不是硬件专家,我不确定我们在谈论多少性能。
  • 嗯,@thecoop 似乎在为您提供基准方面做得很好 - 正如我所说,这样的基本任务发生了很多很多,我愿意打赌,在 99.9999% 的情况下,永远不会有任何风险会发生溢出。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-18
  • 1970-01-01
相关资源
最近更新 更多