C# 您是否为特定问题编写例外或一般例外?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21652/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-01 09:08:18  来源:igfitidea点击:

Do you write exceptions for specific issues or general exceptions?

提问by SCdF

I have some code that gives a user id to a utility that then send email to that user.

我有一些代码可以为实用程序提供用户 ID,然后向该用户发送电子邮件。

emailUtil.sendEmail(userId, "foo");

public void sendEmail(String userId, String message) throws MailException {
    /* ... logic that could throw a MailException */
}

MailExceptioncould be thrown for a number of reasons, problems with the email address, problems with the mail template etc.

MailException可能有多种原因,电子邮件地址问题,邮件模板问题等。

My question is this: do you create a new Exception type for every one of these exceptions and then deal with them individually or do you create one MailException and then store something in the exception (something computer-readable, not the description text) that allows us to do different things based on what actually happened.

我的问题是:您是为这些异常中的每一个创建一个新的异常类型,然后单独处理它们,还是创建一个 MailException,然后在异常中存储一些内容(计算机可读的内容,而不是描述文本),允许我们根据实际发生的事情做不同的事情。

Edit:As a clarification, the exceptions aren't for logs and what-not, this relates to how code reacts to them. To keep going with the mail example, let's say that when we send mail it could fail because you don't have an email address, or it could because you don't have a validemail address, or it could fail.. etc.

编辑:作为澄清,例外不适用于日志和其他内容,这与代码对它们的反应有关。继续使用邮件示例,假设我们发送邮件时可能会因为您没有电子邮件地址而失败,或者可能是因为您没有有效的电子邮件地址,或者可能会失败……等等。

My code would want to react differently to each of these issues (mostly by changing the message returned to the client, but actual logic as well).

我的代码希望对这些问题中的每一个做出不同的反应(主要是通过更改返回给客户端的消息,但也更改实际逻辑)。

Would it be best to have an exception implementation for each one of these issues or one umbrella exception that had something internal to it (an enum say) that let the code distinguish what kind of issue it was.

最好为这些问题中的每一个都有一个异常实现,或者有一个内部异常(枚举说)的伞形异常,让代码区分它是什么类型的问题。

采纳答案by Mnementh

I usually start with a general exception and subclass it as needed. I always can catch the general exception (and with it all subclassed exceptions) if needed, but also the specific.

我通常从一般异常开始,然后根据需要将其子类化。如果需要,我总是可以捕获一般异常(以及所有子类异常),但也可以捕获特定异常。

An example from the Java-API is IOException, that has subclasses like FileNotFoundException or EOFException (and much more).

Java-API 中的一个示例是 IOException,它具有像 FileNotFoundException 或 EOFException(等等)这样的子类。

This way you get the advantages of both, you don't have throw-clauses like:

通过这种方式,您可以获得两者的优点,您没有像这样的 throw 子句:

throws SpecificException1, SpecificException2, SpecificException3 ...

a general

一个将军

throws GeneralException

is enough. But if you want to have a special reaction to special circumstances you can always catch the specific exception.

足够。但是如果你想对特殊情况有特殊反应,你总是可以捕捉到特定的异常。

回答by stimms

It depends on what your application is doing. You might want to throw individual exceptions in cases like

这取决于您的应用程序在做什么。您可能希望在以下情况下抛出个别异常

  • The application is high availability
  • Sending e-mail is particularly important
  • The scope of the application is small and sending e-mail is a large part of it
  • The application will be deployed to a site which is remote and you will only get logs for debugging
  • You can recover from some subset of the exceptions encapsulated in the mailException but not others
  • 应用高可用
  • 发送电子邮件尤为重要
  • 应用范围小,发送邮件占很大一部分
  • 该应用程序将部署到远程站点,您将只获得用于调试的日志
  • 您可以从封装在 mailException 中的某些异常子集中恢复,但不能从其他子集中恢复

In most cases I would say just log the text of the exception and don't waste your time granularizing already pretty granular exceptions.

在大多数情况下,我会说只记录异常的文本,不要浪费时间细化已经非常细化的异常。

回答by jm.

In my code, I find that MOST exceptions percolate up to a UI layer where they are caught by my exception handlers which simply display a message to the user (and write to the log). It's an unexpected exception, after all.

在我的代码中,我发现大多数异常会渗透到 UI 层,在那里它们被我的异常处理程序捕获,这些异常处理程序只是向用户显示一条消息(并写入日志)。毕竟,这是一个意外的例外。

Sometimes, I do want to catch a specific exception (as you seem to want to do). You'll probably find, however, that this is somewhat rare and that it is indicative of using exceptions to control logic -- which is inefficient (slow) and often frowned upon.

有时,我确实想捕获特定的异常(正如您似乎想要做的那样)。但是,您可能会发现这种情况很少见,并且表明使用异常来控制逻辑——这是低效(缓慢)并且经常被人反对的。

So using your example, if you want to run some special logic when the email server is not configured, you may want to add a method to the emailUtil object like:

因此,使用您的示例,如果您想在未配置电子邮件服务器时运行一些特殊逻辑,您可能需要向 emailUtil 对象添加一个方法,例如:

public bool isEmailConfigured()

public bool isEmailConfigured()

... call that first, instead of looking for a specific exception.

...首先调用它,而不是寻找特定的异常。

When an exception does happen, it really means that the situation was completely unexpected and the code can't handle it -- so the best you can do is report it to the user (or write it to a log or restart )

当异常确实发生时,这确实意味着情况完全出乎意料并且代码无法处理它——所以你能做的最好的事情就是将它报告给用户(或将其写入日志或重新启动)

As for having an exception hierarchy vs exceptions-with-error-codes-in-them, I typically do the latter. It's easier to add new exceptions, if you just need to define a new error constant instead of a whole new class. But, it doesn't matter much as long as you try to be consistent throughout your project.

至于具有异常层次结构与包含错误代码的异常,我通常会选择后者。如果您只需要定义一个新的错误常量而不是一个全新的类,那么添加新的异常会更容易。但是,只要您尝试在整个项目中保持一致,这并不重要。

回答by NotMe

Instead of using exceptions, I tend to return a list of status objects from methods that may have problems executing. The status objects contain a severity enum (information, warning, error, ...) a status object name like "Email Address" and a user readable message like "Badly formatted Email Address"

我倾向于从可能有执行问题的方法中返回一个状态对象列表,而不是使用异常。状态对象包含严重性枚举(信息、警告、错误等)、状态对象名称(如“电子邮件地址”)和用户可读消息(如“格式错误的电子邮件地址”)

The calling code would then decide which to filter up to the UI and which to handle itself.

然后调用代码将决定哪些要过滤到 UI,哪些要自己处理。

Personally, I think exceptions are strictly for when you can't implement a normal code solution. The performance hit and handling restrictions are just a bit too much for me.

就我个人而言,我认为异常仅限于无法实现正常代码解决方案的情况。性能冲击和处理限制对我来说有点太多了。

Another reason for using a list of status objects is that identifying multiple errors (such as during validation) is MUCH easier. After all, you can only throw one exception which must be handled before moving on.

使用状态对象列表的另一个原因是识别多个错误(例如在验证期间)要容易得多。毕竟,您只能抛出一个必须在继续之前处理的异常。

Imagine a user submitting an email that had a malformed destination address and contained language that you are blocking. Do you throw the malformed email exception, then, after they fix that and resubmit, throw a bad language exception? From a user experience perspective dealing with all of them at once is a better way to go.

想象一下,用户提交的电子邮件的目标地址格式错误,并且包含您阻止的语言。您是否抛出格式错误的电子邮件异常,然后在他们修复并重新提交后抛出错误的语言异常?从用户体验的角度来看,同时处理所有这些是更好的方法。

UPDATE:combining answers

更新:结合答案

@Jonathan: My point was that I can evaluate the action, in this case sending an email, and send back multiple failure reasons. For example, "bad email address", "blank message title", etc..

@Jonathan:我的观点是我可以评估操作,在这种情况下发送电子邮件,并发回多个失败原因。例如,“错误的电子邮件地址”、“空白邮件标题”等。

With an exception, you're limited to just percolating the one problem then asking the user to resubmit at which point they find out about a second problem. This is really bad UI design.

除了一个例外,您只能解决一个问题,然后要求用户重新提交,此时他们会发现第二个问题。这真是糟糕的 UI 设计。

Reinventing the wheel.. possibly. However, most applications should analyze the whole transaction in order to give the best possible information to the user. Imagine if your compiler stopped dead at the first error. You then fix the error and hit compile again only to have it stop again for a different error. What a pain in the butt. To me, that's exactly the problem with throwing exceptions and hence the reason I said to use a different mechanism.

重新发明轮子……可能。但是,大多数应用程序应该分析整个事务,以便为用户提供尽可能好的信息。想象一下,如果您的编译器在第一个错误时停止运行。然后您修复错误并再次点击编译只是为了让它再次因不同的错误而停止。屁股好痛啊。对我来说,这正是抛出异常的问题,也是我说使用不同机制的原因。

回答by FlySwat

@Chris.Lively

@Chris.Lively

You know you can pass a message in your exception, or even the "status codes". You are reinventing the wheel here.

你知道你可以在你的异常中传递一条消息,甚至是“状态代码”。你在这里重新发明轮子。

回答by dlinsin

I tend to have less Exception types, although it's not really the OO way to do it. Instead I put an enum to my custom Exceptions, which classifies the Exception. Most of the time I have a custom base Exception, which holds on to a couple of members, which can be overridden or customized in derived Exception types.

我倾向于使用较少的 Exception 类型,尽管这并不是真正的 OO 方式。相反,我将一个枚举放在我的自定义异常中,它对异常进行分类。大多数时候我有一个自定义的基本异常,它持有几个成员,可以在派生的异常类型中覆盖或自定义。

A couple of months ago I bloggedabout the idea of how to internationalize Exceptions. It includes some of the ideas mentioned above.

几个月前,我写了一篇关于如何将异常国际化的想法的博客。它包括上面提到的一些想法。

回答by niklasfi

I would just go by

我只是路过

throw new exception("WhatCausedIt")

if you want to handle your exceptions, you could pass a code instead of "WhatCausedIt" an then react to the different answers with a switch statement.

如果你想处理你的异常,你可以传递一个代码而不是“WhatCausedIt”,然后用 switch 语句对不同的答案做出反应。

回答by Telcontar

While you can differenciate the code execution looking the exception don't matter if it's done by the "catch exceptionType hierarchy mode" or by "if(...) else...exception code mode"

虽然您可以通过“捕获异常类型层次结构模式”或“if(...) else...异常代码模式”来区分查看异常的代码执行,但并不重要

but if you are developing software wich is going to be used by other people, like a library i think it's usefull create your own exception types to notice the other people that your sofware can throw other exceptions than the normal ones, and they better catch and resolve them.

但是,如果您正在开发将被其他人使用的软件,例如库,我认为创建您自己的异常类型以通知其他人您的软件可以抛出其他异常而不是正常异常是有用的,并且他们更好地捕获和解决它们。

When i use a library and their methods simply launch an 'Exception' i allways wonder: What can cause this exception?, how must my program react?, if there is a javadoc maybe the cause will be explained, but mustly of times there is not a javadoc or the exception is not explained. Too much overhead witch can be avoided with a WellChossenExceptionTypeName

当我使用一个库并且他们的方法只是启动一个“异常”时,我总是想知道:什么会导致这个异常?我的程序必须如何反应?,如果有 javadoc 可能会解释原因,但肯定有很多次不是 javadoc 或未解释异常。使用 WellChossenExceptionTypeName 可以避免过多的开销

回答by Jim

It depends on whether the code that catches the exception needs to differentiate between exceptions or whether you are just using exceptions to fail out to an error page. If you need to differentiate between a NullReference exception and your custom MailException higher up in the call stack, then spend the time and write it. But most of the time programmers just use exceptions as a catch all to throw up an error on the web page. In this case you are just wasting effort on writing a new exception.

这取决于捕获异常的代码是否需要区分异常,或者您是否只是使用异常来失败到错误页面。如果您需要区分 NullReference 异常和调用堆栈中更高层的自定义 MailException,请花时间编写它。但是大多数时候程序员只是使用异常作为捕获所有内容来在网页上抛出错误。在这种情况下,您只是在浪费精力编写新的异常。

回答by abigblackman

I think a combination of the above is going to give you the best result.

我认为以上的组合会给你最好的结果。

You can throw different exceptions depending on the problem. e.g. Missing email address = ArgumentException.

您可以根据问题抛出不同的异常。例如缺少电子邮件地址 = ArgumentException。

But then in the UI layer you can check the exception type and, if need be, the message and then display a appropriate message to the user. I personally tend to only show a informational message to the user if a certain type of exception is thrown (UserException in my app). Of course you should scrub and verify user input as much as possible further up the stack to make sure any exceptions are generated by truly unlikely scenarios, not as a filter for malformed emails which can easily be checked with a regex.

但是在 UI 层中,您可以检查异常类型,如果需要,还可以检查消息,然后向用户显示适当的消息。如果抛出某种类型的异常(我的应用程序中的 UserException),我个人倾向于只向用户显示信息性消息。当然,您应该尽可能多地在堆栈中进一步清理和验证用户输入,以确保任何异常都是由真正不可能的场景生成的,而不是作为格式错误的电子邮件的过滤器,可以轻松地使用正则表达式进行检查。

I also wouldn't worry about the performance implications of catching an exception from user input. The only time you are going to see performance problems from exceptions is when they are being thrown and caught in a loop or similar.

我也不会担心从用户输入中捕获异常的性能影响。您唯一会看到异常导致的性能问题的时间是它们被抛出并被循环或类似的捕获。