我有一个类,它有两个int
字段x
和y
,以及一个方法Increment
,分别递增这两个字段dx
和dy
。我想防止我的类的状态被静默算术溢出破坏(这将导致x
或y
两者都变为负数),所以我明确地增加了checked
块中的字段:
class MyClass
{
private int x;
private int y;
public void Increment(int dx, int dy)
{
checked { x += dx; y += dy; }
}
}
这应该确保在算术溢出的情况下,调用者将收到一个OverflowException
,并且我的班级的状态将保持不变。但是后来我意识到,在已经成功递增y
之后,可能会在 的增量中发生算术溢出,从而导致不同类型的状态损坏,其破坏性不亚于第一种。x
所以我改变了这样的Increment
方法的实现:
public void Increment2(int dx, int dy)
{
int x2, y2;
checked { x2 = x + dx; y2 = y + dy; }
x = x2; y = y2;
}
这似乎是该问题的合乎逻辑的解决方案,但现在我担心编译器可能会“优化”我精心设计的实现,并以允许在添加x
之前发生分配的方式重新排序指令y + dy
,从而再次导致状态损坏. 我想问一下,根据 C# 规范,这种不受欢迎的情况是否可能。
我也在考虑删除checked
关键字,而是在启用“检查算术溢出”选项(<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
)的情况下编译我的项目。关于方法内指令的可能重新排序,这会产生什么不同Increment
吗?
更新:使用元组解构可以实现更简洁的算术溢出安全实现。这个版本与详细实现有什么不同(不太安全)吗?
public void Increment3(int dx, int dy)
{
(x, y) = checked((x + dx, y + dy));
}
澄清:旨在MyClass
用于单线程应用程序。线程安全不是问题(我知道它不是线程安全的,但没关系)。