【发布时间】:2010-10-18 06:44:01
【问题描述】:
为了避免我在 Google 上搜索到的所有标准答案,我将提供一个大家都可以随意攻击的示例。
C# 和 Java(以及太多其他)有很多类型的一些“溢出”行为我根本不喜欢(例如 type.MaxValue + type.SmallestValue == type.MinValue 例如:int.MaxValue + 1 == int.MinValue)。
但是,看到我的恶毒本性,我会通过将这种行为扩展到,让我们说覆盖 DateTime 类型来增加对这种伤害的侮辱。 (我知道DateTime 在 .NET 中是密封的,但为了这个示例,我使用的伪语言与 C# 完全相同,只是 DateTime 没有密封)。
重写的Add 方法:
/// <summary>
/// Increments this date with a timespan, but loops when
/// the maximum value for datetime is exceeded.
/// </summary>
/// <param name="ts">The timespan to (try to) add</param>
/// <returns>The Date, incremented with the given timespan.
/// If DateTime.MaxValue is exceeded, the sum wil 'overflow' and
/// continue from DateTime.MinValue.
/// </returns>
public DateTime override Add(TimeSpan ts)
{
try
{
return base.Add(ts);
}
catch (ArgumentOutOfRangeException nb)
{
// calculate how much the MaxValue is exceeded
// regular program flow
TimeSpan saldo = ts - (base.MaxValue - this);
return DateTime.MinValue.Add(saldo)
}
catch(Exception anyOther)
{
// 'real' exception handling.
}
}
当然 if 可以很容易地解决这个问题,但事实仍然是我只是看不出为什么你不能使用异常(从逻辑上讲,我可以看到当性能是一个问题时,在某些情况下异常应该避免)。
我认为在许多情况下,它们比 if 结构更清晰,并且不会破坏该方法正在制定的任何合同。
恕我直言,“永远不要将它们用于常规程序流程”的反应似乎每个人的反应都没有那么好,因为这种反应的强度可以证明是合理的。
还是我弄错了?
我读过其他帖子,处理各种特殊情况,但我的观点是,如果你们都是这样的话,这没有什么问题:
- 清除
- 遵守您的方法合同
向我开枪。
【问题讨论】:
-
+1 我也有同感。除了性能之外,避免控制流异常的唯一充分理由是调用者代码的返回值将更具可读性。
-
是:如果发生某些事情则返回 -1,如果发生其他事情则返回 -2,等等...真的比异常更具可读性吗?
-
很遗憾,一个人因为说真话而受到负面声誉:您的示例不可能用 if 语句编写。 (这并不是说它是正确/完整的。)
-
我认为,有时抛出异常可能是您唯一的选择。例如,我有一个业务组件,它通过查询数据库在其构造函数中初始化其内部状态。有时,数据库中没有适当的数据可用。在构造函数中抛出异常是有效取消对象构造的唯一方法。这在类的合同(在我的例子中是 Javadoc)中明确说明,所以我没有问题客户端代码可以(并且应该)在创建组件时捕获该异常并从那里继续。
-
既然您提出了假设,那么您也有责任引用确凿的证据/理由。对于初学者,请说出您的代码优于更短的、自我记录的
if语句的一个 原因。你会发现这很难。换句话说:您的前提是有缺陷的,因此您从中得出的结论是错误的。
标签: exception language-agnostic