何时使用新的异常类型

时间:2022-01-21 23:17:36

What are the guidelines for when to create a new exception type instead of using one of the built-in exceptions in .Net?

什么时候创建新的异常类型而不是使用.Net中的内置异常?

The problem that got me thinking is this. I have a WCF service, which is a basic input-output service. If the service is unable to create an output, because the input is invalid, I want to throw an exception, but which one?

让我思考的问题是这个。我有一个WCF服务,这是一个基本的输入输出服务。如果服务无法创建输出,因为输入无效,我想抛出异常,但是哪一个?

Right now I'm just throwing system.Exception, but this doesn't feel right to me, I don't know why, it just feels wrong. One thing that bugs me, if I test it with a unit test and I expect the system.Exception to be thrown. The exception could as well be thrown by the framework or other code and not by the code I excepted to throw. The test would then pass, as I get the expected exception, but it should have failed.

现在我只是抛出system.Exception,但这对我来说感觉不对,我不知道为什么,它只是感觉不对。有一件事让我烦恼,如果我用单元测试测试它,我希望抛出system.Exception。框架或其他代码也可以抛出异常,而不是我抛出的代码抛出的异常。然后测试将通过,因为我得到预期的异常,但它应该失败。

What do you recommend?

你有什么建议?

8 个解决方案

#1


15  

Avoid throwing System.Exception or System.ApplicationException yourself, as they are too general.

避免自己抛出System.Exception或System.ApplicationException,因为它们太笼统了。

For WCF services there are Fault Contracts - a generic exception that you can tell subscibers to handle.

对于WCF服务,存在故障合同 - 您可以告诉子公司要处理的一般例外。

Flag the interface with:

将接口标记为:

[FaultContract( typeof( LogInFault ) )]
void LogIn( string userName, string password, bool auditLogin );

Then if there is an exception you can throw this specific fault:

然后,如果有异常,您可以抛出此特定错误:

throw new FaultException<LogInFault>( new LogInFault(), "message" );

Use the [DataContract] serialisation on your fault - this saves you from having to handle all the serialisation stuff exceptions normally require.

对故障使用[DataContract]序列化 - 这使您无需处理通常需要的所有序列化内容。

#2


7  

Definitely avoid throwing System.Exception for anything other than throwaway code.

绝对避免为抛弃代码以外的任何东西抛出System.Exception。

If an argument to a method is invalid, throw ArgumentException (or some derived, more specific exception). Consult the docs for existing exceptions before creating your own - but it can often be useful to do so. (You can derive your own type of exception from ArgumentException, of course - if you've got some particular type of condition which you want to indicate from multiple places, creating a new type gives more information than just putting it in the error message.)

如果方法的参数无效,则抛出ArgumentException(或某些派生的,更具体的异常)。在创建自己的异常之前,请查阅文档以获取现有异常 - 但这样做通常很有用。 (当然,您可以从ArgumentException派生自己的异常类型 - 如果您想要从多个位置指示某种特定类型的条件,则创建新类型会提供更多信息,而不仅仅是将其放入错误消息中。 )

Now error handling in WCF may well be different to error handling within the "normal" framework - I suggest you refer to WCF-specific docs/books for that.

现在,WCF中的错误处理可能与“正常”框架中的错误处理不同 - 我建议您参考WCF特定的文档/书籍。

#3


2  

It's not a good idea to throw System.Exception. The biggest reason for this is the effect it has on the calling code. How should they handle the exception? If the calling code is going to handle the exception, then they have to catch every exception, which is probably not the best thing for them to do.

抛出System.Exception并不是一个好主意。最大的原因是它对调用代码的影响。他们应该如何处理这个例外?如果调用代码将处理异常,那么他们必须捕获每个异常,这可能不是他们做的最好的事情。

If a circumstance isn't covered by one of the standard exceptions, then you should create a new Exception object if the exception is something that calling code would be expected to handle as a special case.

如果其中一个标准异常未涵盖某种情况,那么您应该创建一个新的Exception对象,如果异常是调用代码作为特殊情况应该处理的内容。

#4


2  

System.Exception should only be used as a base class for Exceptions, never be thrown directly.

System.Exception应该只用作异常的基类,永远不要直接抛出。

The Framework offers already a lot of valid Exception classes like ArgumentException, ArgumentNullException, InvalidOperationException, FormatException, OverflowException, etc...

Framework提供了许多有效的Exception类,如ArgumentException,ArgumentNullException,InvalidOperationException,FormatException,OverflowException等......

You say you are doing I/O stuff, so a good idea is to look at similar operations in the framework (like int.Parse) and throw the same exceptions for similar errors.

你说你正在做I / O的东西,所以一个好主意是在框架中查看类似的操作(比如int.Parse)并为类似的错误抛出相同的异常。

Or derive your own exception class from an existing exception class if none of them really fits your needs.

或者从现有的异常类派生自己的异常类,如果它们都不能满足您的需求。

#5


2  

If you throw System.Exception, then the caller must catch System.Exception. Both sides of this are a no-no, since it leaves us telling the user "that didn't work", rather than something more useful.

如果抛出System.Exception,则调用者必须捕获System.Exception。这两方面都是禁忌,因为它让我们告诉用户“没有用”,而不是更有用的东西。

An ArgumentException is useful if the caller passed in an invalid argument. If your function has an int parameter that you need to be an even number, then you would throw and ArgumentException telling the caller what parameter was invalid and why. However, if all arguments were valid but there is still a problem, you'll probably need a custom exception. This way the caller can tell the user excatly what went wrong.

如果调用者传入了无效参数,则ArgumentException非常有用。如果你的函数有一个你需要是偶数的int参数,那么你会抛出并且ArgumentException告诉调用者什么参数是无效的以及为什么。但是,如果所有参数都有效但仍存在问题,则可能需要自定义异常。通过这种方式,呼叫者可以激动地告诉用户出了什么问题。

The test for me is really on the calling side. If I would have a dozen catches that all did the same thing, then I really only needed one exception. However, if I had one catch and would have a statement telling the user one of three things went wrong, then I really needed three unique exceptions.

对我的测试真的是在呼唤方面。如果我有十几个捕获所有都做同样的事情,那么我真的只需要一个例外。但是,如果我有一个捕获并且会有一个声明告诉用户三个出错的地方之一,那么我真的需要三个独特的例外。

#6


1  

What are the guidelines for when to create a new exception type instead of using one of the built-in exceptions in .Net?

什么时候创建新的异常类型而不是使用.Net中的内置异常?

When there is no suitable predefined exception class.
.NET FW is very rich, often you can find predefined exception.

没有合适的预定义异常类时。 .NET FW非常丰富,通常可以找到预定义的异常。

If the service is unable to create an output, because the input is invalid

如果服务无法创建输出,则因为输入无效

ArgumentException Class (System)

ArgumentException类(系统)

The exception that is thrown when one of the arguments provided to a method is not valid.

提供给方法的其中一个参数无效时引发的异常。

#7


0  

Always create a new exception type (or use a standard type if it suits you).

始终创建新的异常类型(如果适合您,请使用标准类型)。

In that case you can handle the exceptions as a group.

在这种情况下,您可以将异常作为一个组来处理。

#8


0  

As previous posters have stated, you shouldn't be throwing System.Exception. In fact, if you ran FxCop on your code, it would flag that as a rule violation.

正如之前的海报所述,你不应该抛出System.Exception。实际上,如果您在代码上运行FxCop,它会将其标记为规则违规。

I recommend having a look at Chapter 18 of Applied .NET Framework Programming, or chapter 19 of the more recent CLR via C# (2nd edition) for detailed guidance. Richter does an excellent job of correcting the misconceptions that a lot of developers hold about exceptions.

我建议您查看Applied .NET Framework Programming的第18章,或者通过C#(第2版)查看最近的CLR的第19章,以获取详细的指导。里希特在纠正许多开发人员对异常的误解方面做得非常出色。

Both books contain a list of the exceptions defined by the Framework Class Library. Look at the list and figure out the most specific exceptions possible that your code can throw. If you can recover from an exception, do so in that catch block. If you have need of multiple catch blocks, organize them from the most specific to the least specific. Create a custom exception if you can't find one in the existing list that suits the situation.

这两本书都包含框架类库定义的例外列表。查看列表并找出代码可能抛出的最具体的异常。如果您可以从异常中恢复,请在该catch块中执行此操作。如果您需要多个catch块,请将它们从最具体到最不具体的组织起来。如果在现有列表中找不到适合该情况的自定义异常,请创建自定义异常。

#1


15  

Avoid throwing System.Exception or System.ApplicationException yourself, as they are too general.

避免自己抛出System.Exception或System.ApplicationException,因为它们太笼统了。

For WCF services there are Fault Contracts - a generic exception that you can tell subscibers to handle.

对于WCF服务,存在故障合同 - 您可以告诉子公司要处理的一般例外。

Flag the interface with:

将接口标记为:

[FaultContract( typeof( LogInFault ) )]
void LogIn( string userName, string password, bool auditLogin );

Then if there is an exception you can throw this specific fault:

然后,如果有异常,您可以抛出此特定错误:

throw new FaultException<LogInFault>( new LogInFault(), "message" );

Use the [DataContract] serialisation on your fault - this saves you from having to handle all the serialisation stuff exceptions normally require.

对故障使用[DataContract]序列化 - 这使您无需处理通常需要的所有序列化内容。

#2


7  

Definitely avoid throwing System.Exception for anything other than throwaway code.

绝对避免为抛弃代码以外的任何东西抛出System.Exception。

If an argument to a method is invalid, throw ArgumentException (or some derived, more specific exception). Consult the docs for existing exceptions before creating your own - but it can often be useful to do so. (You can derive your own type of exception from ArgumentException, of course - if you've got some particular type of condition which you want to indicate from multiple places, creating a new type gives more information than just putting it in the error message.)

如果方法的参数无效,则抛出ArgumentException(或某些派生的,更具体的异常)。在创建自己的异常之前,请查阅文档以获取现有异常 - 但这样做通常很有用。 (当然,您可以从ArgumentException派生自己的异常类型 - 如果您想要从多个位置指示某种特定类型的条件,则创建新类型会提供更多信息,而不仅仅是将其放入错误消息中。 )

Now error handling in WCF may well be different to error handling within the "normal" framework - I suggest you refer to WCF-specific docs/books for that.

现在,WCF中的错误处理可能与“正常”框架中的错误处理不同 - 我建议您参考WCF特定的文档/书籍。

#3


2  

It's not a good idea to throw System.Exception. The biggest reason for this is the effect it has on the calling code. How should they handle the exception? If the calling code is going to handle the exception, then they have to catch every exception, which is probably not the best thing for them to do.

抛出System.Exception并不是一个好主意。最大的原因是它对调用代码的影响。他们应该如何处理这个例外?如果调用代码将处理异常,那么他们必须捕获每个异常,这可能不是他们做的最好的事情。

If a circumstance isn't covered by one of the standard exceptions, then you should create a new Exception object if the exception is something that calling code would be expected to handle as a special case.

如果其中一个标准异常未涵盖某种情况,那么您应该创建一个新的Exception对象,如果异常是调用代码作为特殊情况应该处理的内容。

#4


2  

System.Exception should only be used as a base class for Exceptions, never be thrown directly.

System.Exception应该只用作异常的基类,永远不要直接抛出。

The Framework offers already a lot of valid Exception classes like ArgumentException, ArgumentNullException, InvalidOperationException, FormatException, OverflowException, etc...

Framework提供了许多有效的Exception类,如ArgumentException,ArgumentNullException,InvalidOperationException,FormatException,OverflowException等......

You say you are doing I/O stuff, so a good idea is to look at similar operations in the framework (like int.Parse) and throw the same exceptions for similar errors.

你说你正在做I / O的东西,所以一个好主意是在框架中查看类似的操作(比如int.Parse)并为类似的错误抛出相同的异常。

Or derive your own exception class from an existing exception class if none of them really fits your needs.

或者从现有的异常类派生自己的异常类,如果它们都不能满足您的需求。

#5


2  

If you throw System.Exception, then the caller must catch System.Exception. Both sides of this are a no-no, since it leaves us telling the user "that didn't work", rather than something more useful.

如果抛出System.Exception,则调用者必须捕获System.Exception。这两方面都是禁忌,因为它让我们告诉用户“没有用”,而不是更有用的东西。

An ArgumentException is useful if the caller passed in an invalid argument. If your function has an int parameter that you need to be an even number, then you would throw and ArgumentException telling the caller what parameter was invalid and why. However, if all arguments were valid but there is still a problem, you'll probably need a custom exception. This way the caller can tell the user excatly what went wrong.

如果调用者传入了无效参数,则ArgumentException非常有用。如果你的函数有一个你需要是偶数的int参数,那么你会抛出并且ArgumentException告诉调用者什么参数是无效的以及为什么。但是,如果所有参数都有效但仍存在问题,则可能需要自定义异常。通过这种方式,呼叫者可以激动地告诉用户出了什么问题。

The test for me is really on the calling side. If I would have a dozen catches that all did the same thing, then I really only needed one exception. However, if I had one catch and would have a statement telling the user one of three things went wrong, then I really needed three unique exceptions.

对我的测试真的是在呼唤方面。如果我有十几个捕获所有都做同样的事情,那么我真的只需要一个例外。但是,如果我有一个捕获并且会有一个声明告诉用户三个出错的地方之一,那么我真的需要三个独特的例外。

#6


1  

What are the guidelines for when to create a new exception type instead of using one of the built-in exceptions in .Net?

什么时候创建新的异常类型而不是使用.Net中的内置异常?

When there is no suitable predefined exception class.
.NET FW is very rich, often you can find predefined exception.

没有合适的预定义异常类时。 .NET FW非常丰富,通常可以找到预定义的异常。

If the service is unable to create an output, because the input is invalid

如果服务无法创建输出,则因为输入无效

ArgumentException Class (System)

ArgumentException类(系统)

The exception that is thrown when one of the arguments provided to a method is not valid.

提供给方法的其中一个参数无效时引发的异常。

#7


0  

Always create a new exception type (or use a standard type if it suits you).

始终创建新的异常类型(如果适合您,请使用标准类型)。

In that case you can handle the exceptions as a group.

在这种情况下,您可以将异常作为一个组来处理。

#8


0  

As previous posters have stated, you shouldn't be throwing System.Exception. In fact, if you ran FxCop on your code, it would flag that as a rule violation.

正如之前的海报所述,你不应该抛出System.Exception。实际上,如果您在代码上运行FxCop,它会将其标记为规则违规。

I recommend having a look at Chapter 18 of Applied .NET Framework Programming, or chapter 19 of the more recent CLR via C# (2nd edition) for detailed guidance. Richter does an excellent job of correcting the misconceptions that a lot of developers hold about exceptions.

我建议您查看Applied .NET Framework Programming的第18章,或者通过C#(第2版)查看最近的CLR的第19章,以获取详细的指导。里希特在纠正许多开发人员对异常的误解方面做得非常出色。

Both books contain a list of the exceptions defined by the Framework Class Library. Look at the list and figure out the most specific exceptions possible that your code can throw. If you can recover from an exception, do so in that catch block. If you have need of multiple catch blocks, organize them from the most specific to the least specific. Create a custom exception if you can't find one in the existing list that suits the situation.

这两本书都包含框架类库定义的例外列表。查看列表并找出代码可能抛出的最具体的异常。如果您可以从异常中恢复,请在该catch块中执行此操作。如果您需要多个catch块,请将它们从最具体到最不具体的组织起来。如果在现有列表中找不到适合该情况的自定义异常,请创建自定义异常。