嗨,谢谢你的阅读。我是编程和C#和套接字编程的新手。在我的代码中,我尝试捕获问题,以便在我的应用程序中提供故障。以下内容:
catch (ArgumentNullException e)
{
OnNetworkEvents eventArgs = new OnNetworkEvents("Network Unavailable", e.Message);
OnUpdateNetworkStatusMessage(this, eventArgs);
}
catch (EncoderFallbackException e)
{
OnNetworkEvents eventArgs = new OnNetworkEvents("Network Unavailable", e.Message);
OnUpdateNetworkStatusMessage(this, eventArgs);
}
catch (SocketException e)
{
OnNetworkEvents eventArgs = new OnNetworkEvents("Network Unavailable", e.Message);
OnUpdateNetworkStatusMessage(this, eventArgs);
}
catch (ArgumentOutOfRangeException e)
{
OnNetworkEvents eventArgs = new OnNetworkEvents("Network Unavailable", e.Message);
OnUpdateNetworkStatusMessage(this, eventArgs);
}
catch (ObjectDisposedException e)
{
OnNetworkEvents eventArgs = new OnNetworkEvents("Network Unavailable", e.Message);
OnUpdateNetworkStatusMessage(this, eventArgs);
}
我只是想知道我是否可以用一个单独替换这个重复的代码:
catch (Exception e) { handle here}
这会有用吗?
再次感谢。答案 0 :(得分:22)
不,永远不会捕获System.Exception 。我觉得今天的记录很糟糕,但我真的无法强调这一点。你无法处理OutOfMemoryException
或AccessViolationException
,所以不要抓住它!
至于示例代码,我强烈怀疑ArgumentNullException
或ArgumentOutOfRange
异常会对应于网络错误。如果是这样,那可能意味着真正应该捕获此异常的组件不是。
“容错”并不意味着“吃掉所有异常,因此应用程序不会崩溃” - 这意味着实际上知道可能出错的事情并且正确处理。
答案 1 :(得分:16)
作为一般指导原则,不抓住System.Exception
。这是一个坏主意和一个糟糕的代码气味,表明无法掌握目的例外。我相信这是开发人员认为例外是错误而不是触发异常的代码的结果。
我一直在生产代码中看到这种失败,并且当抓住并吞下有效且有用的异常时,它总是掩盖真正的错误,使应用程序处于不良状态。这使得很多更难以找到失败的根本原因。
使用您在此处使用的方法捕获异常或多或少是正确的方法。不过,您可能需要考虑改进一些事项:
通常不会将ArgumentNullException
或ArgumentOutOfRangeException
视为运行时网络故障(除非确实如此)。相反,它应被视为一个逻辑错误,导致程序尽快失败(以便您可以使用调试器尽可能接近故障点进行检查)。这通常意味着根本不会捕获任何ArgumentException
。
考虑检查异常层次结构以找到涵盖您尝试报告的异常的适当基本异常。例如,(我没有查找过),假设三个您的所有例外都来自SocketException
。您可以通过捕获SocketException
而不是三个单独的异常来保存一些输入。但是,只有在报告所有套接字异常时才执行此操作。 (这基本上是你原来试图抓住Exception
)的更严谨的版本
因为每个异常处理程序中的两行都是相同的,所以您可以创建一个函数来在处理程序的一行中完成这两行工作。典型的不重复自己的重构。如果您想要更改报告异常的方式,请考虑更改单个函数比单个处理程序更容易。
几乎所有重要的I / O(网络和文件都会浮现在脑海中)都会引发一个非常重要的异常处理程序链,因为它可能会出错。 看到很多关于可能失败的I / O的错误报告不是反模式,但它可能是一个很好的代码味道。喜欢松散的新鲜香味或新鲜出炉的面包。 :)
答案 2 :(得分:3)
这肯定会抓住所有例外,但这可能是不好的做法。有些例外情况会被隐藏或误传,这会使测试和调试应用程序变得更加困难。
答案 3 :(得分:3)
你可以,但你会失去粒度和单独处理每个问题的能力,这不是最好的做法。通常你会先处理不同类型的异常,就像你有,然后如果你需要对任何未处理的异常做一些事情,你可以在最后添加Exception
。完成后重新抛出它以保留堆栈跟踪并让它冒泡。
保留你最后添加基础案例的内容:
catch (ArgumentNullException e) { ... }
catch (EncoderFallbackException e) { ... }
catch (SocketException e) { ... }
catch (ArgumentOutOfRangeException e) { ... }
catch (ObjectDisposedException e) { ... }
catch (Exception e)
{
// not handled by above exceptions, do something if needed
throw; // after doing what you need, re-throw it
}
答案 4 :(得分:2)
正如之前的所有评论所暗示的那样,您应该捕获所有“已知”异常,其中包含异常特定的catch块和其他未知的,或者更恰当的所有“无法匹配的”异常使用catch (Exception ex) { ... }
或catch { ... }
但是,正如您的代码中所指定的那样,您以相同的方式处理所有类型的异常。所以在这种特殊情况下,输出(你所调用的 Fault Tolerance )将是相同的,但性能会提高(因为运行时不需要将异常类型与给定的类型列表进行比较)。 / p>
故事的道德:在这种特殊情况下使用单一的常见try-catch。但总的来说,避免这种习惯。
答案 5 :(得分:1)
它可以工作,但它也会捕获“空引用”异常以及抛出的任何其他随机异常。
答案 6 :(得分:1)
是的,它会工作,但它不会这样做,因为所有异常而不仅仅是特定的异常都会被捕获。
这通常不是您想要的,因为一般规则是只捕获您知道如何处理的异常。在某些情况下,你需要这样一个catch-all来重定向异常(比如跨线程边界或异步调用)或者做一些清理工作,如果有什么东西 - 什么 - 出错了(但是你经常在做完之后重新抛出异常)你的工作)。
答案 7 :(得分:1)
它将捕获从Exception类继承的所有异常。如果它们都以相同的方式处理,那么你就不应该这样做,因为你不能以同样的方式处理从Exception继承的所有Exceptions。
答案 8 :(得分:1)
我实际上今天早上刚刚在这个主题上读了blog post。
您可以执行帖子评论中提到的内容:
catch(Exception e){
if( e is ArgumentNullException
|| e is EncoderFallbackException
|| e is ...whatever
){
OnNetworkEvents eventArgs = new OnNetworkEvents("Network Unavailable", e.Message);
OnUpdateNetworkStatusMessage(this, eventArgs);
} else { throw; }
}
答案 9 :(得分:0)
虽然你可以做到这一点,但我认为这很糟糕,而不是你想要如何构建代码。
根据例外情况,您可能希望做一些不同的事情。无效IP是与硬件错误不同的问题,依此类推。此外,您可能希望通过委托或使用log4net在某处向某个用户通知UI返回UI。
但那只是我而且我远非专家 - 所以把它当作它的价值
答案 10 :(得分:0)
IMO:
捕获Exception
非常类似于具有参数的方法,这些参数从不比Object
更具体。当然你可以做到,但这是10次中最好的决定吗?
您应该考虑采取哪些措施来简化代码,其中包括以相关的最高定义捕获异常。
例如,在java中我会
try{...}
catch( IOException e ) {...}
捕获所有与IO相关的异常。
有太多东西可以抛出太多不同类型的异常,你通常应该避免使用Exception
的全部内容。