为了避免所有我可以在谷歌上搜索到的标准答案,我将提供一个你们都可以随意攻击的例子。

c#和Java(以及其他很多语言)有很多类型,有些“溢出”行为我一点也不喜欢(例如type。MaxValue +类型。SmallestValue ==类型。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语句表示条件,其预期用途是控制流。

如果您以一种意想不到的方式使用特性,同时又选择不使用为此目的而设计的特性,那么将会有相关的成本。在这种情况下,清晰度和性能没有真正的附加价值。与广泛接受的if语句相比,使用异常能给您带来什么?

换句话说:你能做并不意味着你应该做。

其他回答

您是否曾经尝试调试一个在正常操作过程中每秒引发5个异常的程序?

我有。

该程序相当复杂(它是一个分布式计算服务器),在程序的一侧稍作修改,就可能很容易破坏完全不同的地方的某些东西。

我希望我可以启动程序,然后等待异常发生,但是在正常的操作过程中,在启动过程中大约有200个异常

我的观点是:如果你在正常情况下使用异常,你如何定位异常情况?

当然,还有其他强有力的理由不要过多使用异常,特别是在性能方面

让我们假设您有一个做一些计算的方法。它必须验证许多输入参数,然后返回一个大于0的数字。

使用返回值来表示验证错误,这很简单:如果方法返回的数字小于0,则发生错误。如何判断哪个参数无效?

我记得在我学习C语言的时候,很多函数返回的错误代码是这样的:

-1 - x lesser then MinX
-2 - x greater then MaxX
-3 - y lesser then MinY

etc.

它真的比抛出和捕获异常的可读性更差吗?

我不认为使用异常来进行流控制有什么错。异常有点类似于延续,在静态类型语言中,异常比延续更强大,所以,如果你需要延续,但你的语言没有它们,你可以使用异常来实现它们。

好吧,实际上,如果你需要延续,而你的语言没有,你选择了错误的语言,你应该使用另一种语言。但有时你别无选择:客户端web编程就是最好的例子——没有办法绕过JavaScript。

An example: Microsoft Volta is a project to allow writing web applications in straight-forward .NET, and let the framework take care of figuring out which bits need to run where. One consequence of this is that Volta needs to be able to compile CIL to JavaScript, so that you can run code on the client. However, there is a problem: .NET has multithreading, JavaScript doesn't. So, Volta implements continuations in JavaScript using JavaScript Exceptions, then implements .NET Threads using those continuations. That way, Volta applications that use threads can be compiled to run in an unmodified browser – no Silverlight needed.

我的经验法则是:

如果您可以做任何事情来从错误中恢复,捕获异常 如果这个错误是很常见的(例如。用户尝试使用错误的密码登录),使用returnvalues 如果您不能做任何事情来从错误中恢复,那么就让它不被捕获(或者在主捕获器中捕获它,以半优雅地关闭应用程序)

我认为异常的问题纯粹是从语法的角度来看的(我非常确定性能开销是最小的)。我不喜欢到处都是尝试块。

举个例子:

try
{
   DoSomeMethod();  //Can throw Exception1
   DoSomeOtherMethod();  //Can throw Exception1 and Exception2
}
catch(Exception1)
{
   //Okay something messed up, but is it SomeMethod or SomeOtherMethod?
}

. .另一个例子是,当你需要使用工厂将一些东西赋值给一个句柄时,该工厂可能会抛出异常:

Class1 myInstance;
try
{
   myInstance = Class1Factory.Build();
}
catch(SomeException)
{
   // Couldn't instantiate class, do something else..
}
myInstance.BestMethodEver();   // Will throw a compile-time error, saying that myInstance is uninitalized, which it potentially is.. :(

就我个人而言,我认为你应该为罕见的错误条件(内存不足等)保留异常,而使用returnvalues(值类,结构或枚举)来进行错误检查。

希望我正确理解了你的问题:)

您可以使用锤子的爪来拧螺丝,就像您可以为控制流使用异常一样。这并不意味着这是该特性的预期用途。if语句表示条件,其预期用途是控制流。

如果您以一种意想不到的方式使用特性,同时又选择不使用为此目的而设计的特性,那么将会有相关的成本。在这种情况下,清晰度和性能没有真正的附加价值。与广泛接受的if语句相比,使用异常能给您带来什么?

换句话说:你能做并不意味着你应该做。