C# 自定义异常类

C# 自定义异常类,c#,.net,exception-handling,C#,.net,Exception Handling,我有一个抽象类相机。有一些派生类将处理特定类型的摄影机。每种类型的相机都有自己的异常,而其中一些相机根本没有异常,它们返回一个带有错误类型的枚举 我想知道你们是否同意这种实施方式: 所有特定类都将处理其异常或枚举错误类型,并将其转换为通用异常ex:CameraException:exception并抛出它 这是一个好的/推荐的实现吗?转换为通用异常通常只会隐藏重要信息。 让所有异常继承CameraException可能是一件好事,但如果不同的实现发现CameraException有用,就让它子类

我有一个抽象类相机。有一些派生类将处理特定类型的摄影机。每种类型的相机都有自己的异常,而其中一些相机根本没有异常,它们返回一个带有错误类型的枚举

我想知道你们是否同意这种实施方式:

所有特定类都将处理其异常或枚举错误类型,并将其转换为通用异常ex:CameraException:exception并抛出它


这是一个好的/推荐的实现吗?

转换为通用异常通常只会隐藏重要信息。
让所有异常继承CameraException可能是一件好事,但如果不同的实现发现CameraException有用,就让它子类化。

转换为通用异常通常只会隐藏重要信息。
让所有异常继承CameraException可能是一件好事,但如果不同的实现发现它有用,就让它子类CameraException。

您可能希望将错误概念统一到公共CameraException类层次结构中。如果目标是抽象摄影机实现,那么您应该将错误也抽象到这个公共异常框架中

如果只有特定于实现的异常,那么类的用户在不分析细节的情况下很难准确理解CameraException想要说什么

我建议提供一个逻辑异常框架,然后依赖于实现的摄影机逻辑将解释代码,然后创建正确的相应逻辑摄影机异常

例如,如果您尝试在相机的内存、卡上执行操作,但未插入任何操作,则抛出可以从CameraException继承的NoMemoryCardInCameraException

如果您确实希望这些提供程序详细信息可用,那么您可以在CameraException中有一个名为Detail的属性,或者是一个抽象类或具有特定于实现的详细信息的键值对字典。这样,如果有人真的想从提供者那里挖掘实际的错误代码、枚举等,他们可以

您的目标应该是让普通用户能够捕获逻辑异常并适当地处理它们,而不需要了解具体情况


希望这能澄清一点…

您希望将错误概念统一到一个通用的CameraException类层次结构中。如果目标是抽象摄影机实现,那么您应该将错误也抽象到这个公共异常框架中

如果只有特定于实现的异常,那么类的用户在不分析细节的情况下很难准确理解CameraException想要说什么

我建议提供一个逻辑异常框架,然后依赖于实现的摄影机逻辑将解释代码,然后创建正确的相应逻辑摄影机异常

例如,如果您尝试在相机的内存、卡上执行操作,但未插入任何操作,则抛出可以从CameraException继承的NoMemoryCardInCameraException

如果您确实希望这些提供程序详细信息可用,那么您可以在CameraException中有一个名为Detail的属性,或者是一个抽象类或具有特定于实现的详细信息的键值对字典。这样,如果有人真的想从提供者那里挖掘实际的错误代码、枚举等,他们可以

您的目标应该是让普通用户能够捕获逻辑异常并适当地处理它们,而不需要了解具体情况


希望这能澄清一点…

如果调用方要捕获特定类型,或者某个调用方要了解特定类型并查看其属性,则只应创建新的异常类型

如果不同摄像机类型的呼叫者只执行以下操作:

try
{
    // Do something with some kind of camera
}
catch (CameraException ex)
{
    // Handle the fact that there was a camera problem
}
这样就不需要自定义派生类型的CameraException。没有人关心抛出了什么特定的派生类型

事实上,如果调用方在抛出CameraException时与任何其他类型的异常时没有什么不同,那么就不需要CameraException。只需使用类似InvalidOperationException的内容,并将其与信息性消息属性一起抛出:

throw new InvalidOperationException(
    String.Format("Invalid attempt to set the f-stop to {0} while in video mode",
                  this.FStop));

只有当调用方要捕获特定类型,或者某个调用方要了解特定类型并查看其属性时,才应该创建新的异常类型

如果不同摄像机类型的呼叫者只执行以下操作:

try
{
    // Do something with some kind of camera
}
catch (CameraException ex)
{
    // Handle the fact that there was a camera problem
}
这样就不需要自定义派生类型的CameraException。没有人关心抛出了什么特定的派生类型

事实上,如果调用方在抛出CameraException时与任何其他类型的异常时没有什么不同,那么就不需要CameraException。仅仅 使用类似InvalidOperationException的内容,并将其与信息性消息属性一起抛出:

throw new InvalidOperationException(
    String.Format("Invalid attempt to set the f-stop to {0} while in video mode",
                  this.FStop));

应用程序层应该定义自定义异常类型,而不管Microsoft怎么说。假设有一个抽象的WrappedCamera类,它的派生类作为围绕CanonCamera、NikonCamera、KodakCamera等类的包装,它的未来派生类将作为围绕未来设计的相机类的包装。假设一个类WrappedWaldorCamera包装了WaldorfCamera,当它调用WaldorfCamera.GetPictureCount时,该方法抛出异常WaldorfCamera.ErrorCameraModeException。如果WrappedWaldorfCamera让异常渗透,应用程序将如何处理它?除非应用程序假定所有未知的异常类型都应显示一条消息,但允许程序继续,否则应用程序无法知道WaldorfCamera.ErrorCameraModeException可以安全捕获。相反,如果WrappedWaldorfCamera抛出一个WrappedCamera.CameraModeException,它派生自WrappedCamera.CleanOnConnectionStateException,那么应用程序将知道它应该捕获并处理该异常

BTW,以免有人抱怨整个问题是由WalDofFix相机定义它自己的异常创建的,请考虑情况,如果不是WrdDalWaldfFixt,就让一个无效操作异常渗入。应用程序应该如何处理其中一个


正确的做法是,每个应用程序层至少定义致命和非致命异常类型,通常根据应用程序状态定义几种类型,例如CleanNonConnectStateException表示特定的相机连接对象没有有效的连接;准备好处理的应用程序代码应该捕获异常,而不准备处理的代码应该让异常冒泡到可以处理这种情况的代码,如果异常跨越另一层边界,则重新捕获异常。

应用程序层应该定义自定义异常类型,不管微软怎么说。假设有一个抽象的WrappedCamera类,它的派生类作为围绕CanonCamera、NikonCamera、KodakCamera等类的包装,它的未来派生类将作为围绕未来设计的相机类的包装。假设一个类WrappedWaldorCamera包装了WaldorfCamera,当它调用WaldorfCamera.GetPictureCount时,该方法抛出异常WaldorfCamera.ErrorCameraModeException。如果WrappedWaldorfCamera让异常渗透,应用程序将如何处理它?除非应用程序假定所有未知的异常类型都应显示一条消息,但允许程序继续,否则应用程序无法知道WaldorfCamera.ErrorCameraModeException可以安全捕获。相反,如果WrappedWaldorfCamera抛出一个WrappedCamera.CameraModeException,它派生自WrappedCamera.CleanOnConnectionStateException,那么应用程序将知道它应该捕获并处理该异常

BTW,以免有人抱怨整个问题是由WalDofFix相机定义它自己的异常创建的,请考虑情况,如果不是WrdDalWaldfFixt,就让一个无效操作异常渗入。应用程序应该如何处理其中一个


正确的做法是,每个应用程序层至少定义致命和非致命异常类型,通常根据应用程序状态定义几种类型,例如CleanNonConnectStateException表示特定的相机连接对象没有有效的连接;准备好处理的应用程序代码应该捕获异常,而不准备处理的代码应该让异常冒泡到可以处理这种情况的代码,如果异常跨越另一层边界,则重新捕获异常。

这些异常是什么?什么样的事情会出错?对于异常情况,你希望打电话的人怎么办?例句:试着启动一个断开连接的摄像头。在这种情况下,调用者可以在ui中显示摄像头不可用。您可以通过提供一条消息,说明您试图启动断开连接的摄像头来做到这一点。另外,异常不是更新UI的好方法。我的意思是:try-stuff,catch-MessageBox.Showe.message。显示ex.Message对InvalidOperationException的效果与对某些自定义异常的效果一样。这些异常是什么?什么样的事情会出错?对于异常情况,你希望打电话的人怎么办?例句:试着启动一个断开连接的摄像头。在这种情况下,调用者可以在ui中显示摄像头不可用。您可以通过提供一条消息,说明您试图启动断开连接的摄像头来做到这一点。另外,异常不是更新UI的好方法。我的意思是:try stuff,catch MessageBox.Showe.Messa
哎呀。显示ex.Message对InvalidOperationException的效果与对某些自定义异常的效果一样。不,在当前返回枚举的情况下,可能有调用方正在查看返回值。在这种情况下,您可能应该继续返回错误代码,除非您准备将所有调用者更改为使用异常处理。如果是这样的话,那么有一个可以包含枚举的自定义异常类型是有意义的。调用方仍然可以使用依赖于枚举的代码。调用方将只知道抽象摄影机,他们不关心特定类型是什么!因此,每个派生摄影机类的行为必须相同。如果API没有实例,我将抛出一个实例,其中包含被调用方法返回的错误。在这种情况下,您可能应该继续返回错误代码,除非您准备将所有调用者更改为使用异常处理。如果是这样的话,那么有一个可以包含枚举的自定义异常类型是有意义的。调用方仍然可以使用依赖于枚举的代码。调用方将只知道抽象摄影机,他们不关心特定类型是什么!因此,每个派生摄影机类的行为必须相同。如果API没有实例,我将抛出一个实例,其中包含被调用方法返回的错误。但是人们说,转换为通用异常通常只是隐藏了重要信息。。我想我会在类中抛出expetions,因为API没有自己的异常。API只返回带有错误类型的enum。@Pedro77:这真的、真的取决于您拥有的信息以及它对这个泛型类的用户的重要性。如果是有意义的信息,他们可以对其采取行动,则无论如何创建一个具有公共基本异常类型CameraException的层次结构,但如果是由于逻辑错误导致的异常,即NotConnectedCameraException、NoMemoryCardCameraException、,等等,那么你应该有一个支持逻辑错误的层次结构,并隐藏错误代码。这就是我所想的。但是人们说,转换为通用异常通常只是隐藏了重要信息。。我想我会在类中抛出expetions,因为API没有自己的异常。API只返回带有错误类型的enum。@Pedro77:这真的、真的取决于您拥有的信息以及它对这个泛型类的用户的重要性。如果是有意义的信息,他们可以对其采取行动,则无论如何创建一个具有公共基本异常类型CameraException的层次结构,但如果是由于逻辑错误导致的异常,即NotConnectedCameraException、NoMemoryCardCameraException、,等等,那么你应该有一个支持逻辑错误和隐藏错误代码的层次结构。我认为问题是,异常可能是由那些对Camera类一无所知的人编写的实现部分引发的,因此,这些异常几乎肯定不会从CameraException派生。让这样一个异常在整个应用层中冒泡而不被包装是一个坏主意,由于更高级别的代码无法确定异常来自哪一层,更不用说应该如何处理异常了。我认为问题在于,异常可能是由对Camera类一无所知的人编写的部分实现引发的,因此,这些例外几乎肯定不会源自CameraException。让这样的异常在整个应用程序层中冒泡而不被包装是一个坏主意,因为更高级别的代码无法确定异常来自哪个层,更不用说应该如何处理它了。