简体   繁体   English

C#try {} catch {}

[英]C# try {} catch {}

hi and thanks for reading. 嗨,谢谢你的阅读。 im a newbie in programming and C# and sockets programming. 我是编程和C#和套接字编程的新手。 in my code i try and catch problems to provide fault tolarence in my app. 在我的代码中,我尝试捕获问题,以便在我的应用程序中提供故障。 the following: 下列:

        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);
        }

i was just wondering if i can replace this repetitive code with one single: 我只是想知道我是否可以用一个单一替换这个重复的代码:

catch (Exception e) { handle here}

would this work? 这会有用吗?

thanks again. 再次感谢。

No, never catch System.Exception . 不, 永远不会捕获System.Exception I feel like a broken record today, but I really can't stress this enough. 我觉得今天的记录很糟糕,但我真的无法强调这一点。 You cannot handle an OutOfMemoryException or AccessViolationException , so don't catch it! 你不能处理OutOfMemoryExceptionAccessViolationException ,所以不要抓住它!

As for the example code, I have strong doubts that an ArgumentNullException or ArgumentOutOfRange exception would correspond to a network error. 至于示例代码,我强烈怀疑ArgumentNullExceptionArgumentOutOfRange异常会对应于网络错误。 If it does, it likely means that the component that really should be catching this exception, isn't. 如果是这样,它可能意味着真正应该捕获此异常的组件不是。

"Fault tolerance" does not mean "eat every exception so the app doesn't crash" - it means actually knowing the things that can go wrong and handling them correctly. “容错”并不意味着“吃掉每个例外,因此应用程序不会崩溃” - 这意味着实际上知道可能出错的事情并正确处理它们。

As a general guideline, don't catch System.Exception . 作为一般准则, 请不要捕获System.Exception It's a bad idea and a bad code smell indicative of a failure to grasp the purpose of exceptions. 这是一个坏主意和一个糟糕的代码气味,表明未能掌握异常的目的。 I believe it's the result of a dev's belief that exceptions are the error instead of the code that triggered the exception. 我相信这是开发人员认为异常是错误而不是触发异常的代码的结果。

I see this failure in production code all the time, and it invariably masks real errors as valid and useful exceptions are caught and swallowed, leaving the application in a bad state. 我一直在生产代码中看到这种失败,并且它总是掩盖真正的错误,因为有效和有用的异常被捕获并吞没,使应用程序处于不良状态。 This makes it much trickier to track down the root cause of a failure. 这使得追踪失败的根本原因变得更加棘手。

Catching exceptions using the method you've used here is more-or-less the right way to do it. 使用您在此处使用的方法捕获异常或多或少是正确的方法。 There are a few things you might want to consider improving on, though: 但是,您可能需要考虑改进一些事项:

  1. Don't generally treat an ArgumentNullException or ArgumentOutOfRangeException as a runtime network failure (unless it really is). 通常不会将ArgumentNullExceptionArgumentOutOfRangeException视为运行时网络故障 (除非确实如此)。 Rather, it should be considered a logic error that causes your program to fail as quickly as possible (so that you can check it out with a debugger as close as possible to the point of failure). 相反,它应被视为一个逻辑错误,导致程序尽快失败(以便您可以使用调试器尽可能接近故障点进行检查)。 This frequently means not catching any ArgumentException at all. 这通常意味着根本不捕获任何ArgumentException

  2. Consider examining the exception hierarchy to find an appropriate base exception that covers the exceptions you're trying to report. 考虑检查异常层次结构以查找涵盖您尝试报告的异常的适当基本异常。 Eg, (I haven't looked it up), suppose that three of your exceptions all derived from SocketException . 例如,(我没有查找过),假设你的三个例外都是从SocketException派生的。 You might save some typing by catching a SocketException instead of the three separate exception. 您可以通过捕获SocketException而不是三个单独的异常来保存一些输入。 Only do this if you're reporting all socket exceptions, however. 但是,只有在报告所有套接字异常时才执行此操作。 (This is basically a more disciplined version of your original attempt to just catch Exception ) (这基本上是原始尝试捕获Exception的更严格的版本)

  3. Because both lines in every exception handler are identical, you may create a function to do those two lines of work in a single line in the handler . 因为每个异常处理程序中的两行都是相同的,所以您可以创建一个函数来在处理程序的一行中完成这两行工作 Typical don't-repeat-yourself refactoring. 典型的不重复自己的重构。 If you want to change the way you report your exception, think about how much easier it would be to change a single function than all those individual handlers. 如果要更改报告异常的方式,请考虑更改单个函数比单个处理程序更容易。

  4. Just about any significant I/O (network and file come to mind) is going to entail a pretty significant chain of exception handlers just because there's so much that can go wrong. 几乎任何重要的I / O(网络和文件都会浮现在脑海中)都会引发一个非常重要的异常处理程序链,因为它可能会出错。 Seeing a lot of error reporting around I/O that may fail isn't an anti-pattern, but it may be a good code smell. 看到很多可能失败的I / O错误报告不是反模式,但它可能是一个很好的代码味道。 Like pine-fresh scent or freshly baked bread. 像松香新鲜的香味或新鲜出炉的面包。 :) :)

That will certainly catch all exceptions, but that can be poor practice. 这肯定会抓住所有例外,但这可能是不好的做法。 There are some exceptions that will be hidden or misrepresented that will make testing and debugging your application much more difficult. 有些例外情况会被隐藏或误传,这会使测试和调试应用程序变得更加困难。

You could but you would lose granularity and the ability to handle each issue individually, which isn't the best practice. 你可以,但你会失去粒度和单独处理每个问题的能力,这不是最好的做法。 Usually you would handle different types of exceptions first, just as you have, then if you need to do something with any unhandled exceptions you could add the Exception at the end. 通常,您将首先处理不同类型的异常,就像您一样,如果您需要对任何未处理的异常执行某些操作,则可以在末尾添加Exception Re-throw it once you're done to preserve the stack-trace and let it bubble up. 完成后重新抛出它以保留堆栈跟踪并让它冒泡。

Keep what you have an add a base case at the end: 保留你最后添加的基础案例:

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
}

As all previous comments suggest, you should catch all the "known" exceptions with exception specific catch block and other unknown, or more appropriately, all "unmatched" exceptions with catch (Exception ex) { ... } or just catch { ... } 正如之前的所有评论所暗示的那样,你应该捕获所有“已知”异常,异常特定的catch块和其他未知的,或者更恰当的,所有“不匹配”的异常与catch (Exception ex) { ... }或者只是catch { ... }

However, as specified in your code, you are handling all kind of exceptions in same way. 但是,正如您的代码中所指定的那样,您以相同的方式处理所有类型的异常。 So in this particular case, the output (what you are calling Fault Tolerance ) will be the same, but the performance will improve (since the runtime need not compare exception type with given list of types). 所以在这种特殊情况下,输出(你称之为Fault Tolerance )将是相同的,但性能会提高(因为运行时不需要将异常类型与给定的类型列表进行比较)。

Moral of the story : Use single common try-catch in this particular case. 故事的道德:在这种特殊情况下使用单一的常见尝试。 But in general, avoid such habit. 但总的来说,避免这种习惯。

它会工作,但它也会捕获“空引用”异常和抛出的任何其他随机异常。

Yes it would work , but it would not do the same, since all exceptions and not only the specific ones would be catched. 是的它会起作用 ,但它不会这样做,因为所有的例外而不仅仅是特定的例外。

This is usually not what you want, as the general rule is to catch only exceptions which you know how to handle. 这通常不是您想要的,因为一般规则是只捕获您知道如何处理的异常。 There are some situations where you need such a catch-all to redirect the exception (like accross thread boundaries or in async calls) or do some cleanup work if something - anything - goes wrong (but then you usually re-throw the exception after doing your work). 在某些情况下,你需要这样一个catch-all来重定向异常(比如跨线程边界或异步调用)或者做一些清理工作,如果有什么东西 - 什么 - 出错了(但是你经常在做完之后重新抛出异常)你的工作)。

It would catch all exceptions which inherit from Exception class. 它将捕获从Exception类继承的所有异常。 If they all are handled in the same way you can do it but you shouldn't as you can't handle all Exceptions inherited from Exception in the same way. 如果它们都以相同的方式处理,那么你就不应该这样做,因为你不能以同样的方式处理从Exception继承的所有Exceptions。

I actually just read a blog post on this very topic this morning. 我今天早上刚刚在这个主题上阅读了一篇博文

You could do something like mentioned in the comments of the 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; } 
}

While you can do that , I'd consider it poor practice and not how you'd want to be structuring your code. 虽然你可以做到这一点,但我认为这是一种糟糕的做法,而不是你想要如何构建你的代码。

Depending on the exception you may want to do something different. 根据例外情况,您可能希望做一些不同的事情。 An invalid IP is a different issue than a hardware error and so on. 无效IP是与硬件错误不同的问题,依此类推。 Additionally some errors you might want to notify back to the UI via a delegate or log somewhere using log4net. 此外,您可能希望通过委托或使用log4net在某处通知某些内容来返回UI。

But that's just me and I'm far from an expert - so take it for what it's worth 但那只是我而且我远非专家 - 所以把它当作它的价值

IMO: IMO:

Catching Exception would be pretty similar to having methods with parameters that are never more specific of a class than Object ; 捕获Exception非常类似于具有参数的方法,这些参数从不比Object更具体。 Sure you can do it but is it really the best decision 9 out of 10 times? 当然你可以做到,但它真的是10次中最好的决定吗?

What you should consider doing to simplify your code some is Catch exceptions at the highest definition that is relevant. 您应该考虑采取哪些措施来简化代码,其中包括以相关的最高定义捕获异常。

For instance, in java I would 例如,在java中我会

try{...}
catch( IOException e ) {...}

to catch all IO related exceptions. 捕获所有IO相关的异常。

There are too many things that can throw too many different types of exceptions, you typically should avoid using the catch-all that is Exception . 有太多东西可以抛出太多不同类型的异常,你通常应该避免使用Exception的catch-all。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM