- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在vb.net以及可能的其他.net语言中,可以定义和引发采用通用类参数的异常类。例如,可以合法地定义SomeThingBadHappenedException(Of T),然后抛出并捕获SomethingBadHappened(Of SomeType)。这似乎提供了一种方便的方式来制作一系列异常,而不必为每个异常手动定义构造函数。改进异常类型似乎有助于确保一个捕获的异常实际上是一个预期的异常,而不是成为在调用堆栈中进一步抛出的异常。 Microsoft可能不特别喜欢使用细节严格的自定义异常的想法,但是由于许多预先存在的异常可能来自意外位置(例如,“FileNotFoundException”在第一次调用应该从DLL加载的函数时) )引发和捕获自定义异常似乎比使用现有异常更安全。
我看到的关于自定义异常的最大限制是,由于泛型类参数既不是协变也不是协变(*),所以“将Ex捕获为SomethingBadHappened(Of SomeBaseType)”不会捕获SomethingBadHappened(Of SomeDerivedType)。可以将“将Ex捕获为SomethingBadHappened(Of T,U)”定义为衍生自SomethingBadHappened(Of U),然后抛出“SomethingBadHappened(Of SomeDerivedType,SomeBaseType)”,但这有点笨拙,因此必须始终使用笨拙的形式或省略基本类型的形式(并且不能作为基本类型的异常捕获)。
人们对使用泛型类型的异常的想法有何看法?除了上面提到的以外,还有其他陷阱吗?
(*)如果可以捕获IException(Of Out T As Exception)的派生类,而不仅仅是Exception的派生类,则可以定义协变泛型异常类型。如果IException(Of T)包含类型T的“Self”属性,并且Microsoft可能将这种能力引入.net,并且尝试捕获派生的Exception U也将捕获任何IException(Of U),但这可能太过复杂,不值得。
附录
在现有的异常层次结构中,如果类Foo抛出例如在某些不应该发生但调用者可能必须处理的特殊条件下,InvalidOperationException是一种好方法,即调用者无法捕获这些异常而又不能捕获由于不可预见的条件而导致的异常,其中某些异常应被捕获,而其他一些异常不应该。让Foo类定义自己的异常可以避免这种危险,但是,如果每个“真实”类都定义了一个自定义异常类,则自定义异常类可能很快变得不知所措。拥有CleanFailureException(Of Foo)之类的东西看起来更干净,这表明所请求的操作由于某种原因没有发生,但是状态没有受到干扰,或者是CleanFailureException(Of Foo,Foo.Causes.KeyDuplicated),它将从CleanFailureException(Of Foo)继承,指示失败的更精确原因。
我还没有找到使用通用异常的任何方法,这些方法最终不会让您感到笨拙,但这并不意味着没有其他人可以找到更好的方法。请注意,派生的异常类型可以正常工作。唯一真正的麻烦是,每当引发或捕获故障时,都必须指定导数链中的所有内容。
'定义一些接口(interface),用于指示哪些故障是由其他故障引起的
接口(interface)IFault(T)
终端接口(interface)
接口(interface)IFault(T,U作为IFault(T))
终端接口(interface)
接口(interface)IFault(T,U作为IFault(T),V As IFault(T,U))
终端接口(interface)
派生异常本身。当然,实际代码应包括所有构造函数。
类CleanFailureException
继承异常
子新建(ByVal消息为字符串,ByVal innerException为异常)
MyBase.New(Msg,innerException)
结束子
末级
类CleanFailureException(Of T)
继承CleanFailureException
子新建(ByVal消息为字符串,ByVal innerException为异常)
MyBase.New(Msg,innerException)
结束子
末级
类CleanFailureException(Of T,FaultType如IFault(Of T))
继承CleanFailureException(Of T)
子新建(ByVal消息为字符串,ByVal innerException为异常)
MyBase.New(Msg,innerException)
结束子
末级
类CleanFailureException(Of T,FaultType如IFault(Of T),FaultSubType As IFault(Of T,FaultType))
继承CleanFailureException(Of T,FaultType)
子新建(ByVal消息为字符串,ByVal innerException为异常)
MyBase.New(Msg,innerException)
结束子
末级
类CleanFailureException(T,FaultType作为IFault(T),FaultSubType作为IFault(T,FaultType),FaultSubSubType作为IFault(T,FaultType,FaultSubType))
继承CleanFailureException(Of T,FaultType,FaultSubType)
子新建(ByVal消息为字符串,ByVal innerException为异常)
MyBase.New(Msg,innerException)
结束子
末级
'现在是使用此类异常的示例类
类FileLoader
类错误'有效地用作类中的 namespace
类FileParsingError
实现IFault(Of FileLoader)
末级
类InvalidDigit
实现IFault(Of FileLoader,FileParsingError)
末级
当我要AZeroOrOne时,类GotADollarSign
实现IFault(FileLoader,FileParsingError,InvalidDigit)
末级
类别GotAPercentSignWhenIWantedASix
实现IFault(FileLoader,FileParsingError,InvalidDigit)
末级
类InvalidSeparator
实现IFault(Of FileLoader,FileParsingError)
末级
类SomeOtherError
实现IFault(Of FileLoader)
末级
末级
'现在测试例程抛出上述异常
共享子TestThrow(ByVal WhereOne作为整数)
选择案例
案例0
抛出新的CleanFailureException(Of FileLoader,Faults.FileParsingError,Faults.InvalidDigit,Faults.GotADollarSignWhenIWantedAZeroOrOne)_
(“糟糕”,什么都没有)
情况1
抛出新的CleanFailureException(Of FileLoader,Faults.FileParsingError,Faults.InvalidDigit,Faults.GotAPercentSignWhenIWantedASix)_
(“糟糕”,什么都没有)
情况二
抛出新的CleanFailureException(Of FileLoader,Faults.FileParsingError,Faults.InvalidDigit)_
(“糟糕”,什么都没有)
情况二
抛出新的CleanFailureException(Of FileLoader,Faults.FileParsingError,Faults.InvalidSeparator)_
(“糟糕”,什么都没有)
案例4
抛出新的CleanFailureException(Of FileLoader,Faults.FileParsingError)_
(“糟糕”,什么都没有)
案例5
抛出新的CleanFailureException(Of FileLoader,Faults.SomeOtherError)_
(“糟糕”,什么都没有)
案例6
抛出新的CleanFailureException(Of FileLoader)_
(“糟糕”,什么都没有)
案例7
抛出新的CleanFailureException(Integer)_
(“糟糕”,什么都没有)
结束选择
结束子
'查看如何捕获每种异常类型的例程
共享子TestFaults()
对于i作为整数= 0到7
尝试
TestThrow(i)
以CleanFailureException(FileLoader,Faults.FileParsingError,Faults.InvalidDigit,Faults.GotADollarSignWhenIWantedAZeroOrOne)形式捕获
Debug.Print(“将{0}捕获为GotADollarSignWhenIWantedAZeroOrOne”,例如GetType)
捕获为CleanFailureException(Of FileLoader,Faults.FileParsingError,Faults.InvalidDigit)
Debug.Print(“将{0}捕获为InvalidDigit”,例如,GetType)
捕获为CleanFailureException(Of FileLoader,Faults.FileParsingError)
Debug.Print(“{0}被捕获为FileParsingError”,例如,GetType)
捕获为CleanFailureException(FileLoader)
Debug.Print(“将{0}捕获为FileLoader”,例如,GetType)
捕获为CleanFailureException
Debug.Print(“将{0}捕获为CleanFailureException”,例如,GetType)
结束尝试
下一个
结束子
末级
附录2
使用泛型异常的至少一个优点是,虽然无法使用有用的异常工厂来定义要创建的异常的泛型类型参数,除非人们以某种令人反感的方式使用了Reflection,但是有可能让工厂创建一个包含通用类型参数的异常类。如果有人感兴趣,我可以更新一个代码示例以包括该代码示例。
否则,是否有任何不错的编码模式来定义自定义异常,而不必为每个不同的派生类重复相同的构造函数代码?我真的希望vb.net和/或C#包含一种语法,以指定单个无参数的特定于类的构造函数,并为每个父级重载自动创建 public 构造函数。
附录3
经过进一步的考虑,似乎在很多情况下,真正需要的不是将引发的异常绑定(bind)到类,而是在异常和对象实例之间定义了关系。不幸的是,没有干净的方法来定义“catch SomeExceptionType(ThisParticularFoo)”的概念。最好的选择是用“NoCorruptionOutisde”谓词定义一个自定义基本异常类,然后说“Ex.NoCorruptionOutside(MyObjectInstance)时将Ex捕获为CorruptObjectException”。听上去怎么样?
最佳答案
看来您确实在使这项工作变得比所需的困难。我建议制作这样的异常类:
Public Class CleanFailureException
Inherits Exception
Public Enum FaultType
Unknown
FileParsingError
InvalidDigit
WhateverElse
End Enum
Public Property FaultReason As FaultType
Public Sub New(msg As String, faultReason As FaultType, innerException As Exception)
MyBase.New(msg, innerException)
Me.FaultReason = faultReason
End Sub
End Class
Try
SomeAction()
Catch cfex As CleanFailureException
Select Case cfex.FaultReason
Case CleanFailureException.FaultType.FileParsingError
' Handle error
Case Else
Throw ' don't throw cfex so you preserve stack trace
End Select
Catch ex As AnyOtherException
' Handle this somehow
End Try
SecondaryFaultReason
的属性并提供另一个构造函数。如果您需要为某些FaultTypes在对象上存储一些额外的数据,只需继承CleanFailureException,然后为该FaultType特定的额外数据添加属性。然后,如果需要在异常处理程序中获取额外的数据属性,则可以捕获该子类异常,或者如果不需要,则可以捕获CleanFailureException。我从未见过将泛型用于例外情况,而且我非常确信即使有充分的理由在某个地方进行此操作,您所解释的也不是。
关于.net - 使用带有泛型类型参数的异常是好是坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6671996/
可以用这种方式转换字符串吗?我们有相同的参数,Java 做出了正确的选择。如果值是整数 - 我们调用 parseInt(value),否则如果值是 double 型 - 我们调用 parseDoubl
如果这段代码中有一个愚蠢的错误,我提前道歉,但我似乎无法解决它。我的问题是这样的,我用GCC-8(通过home-brew安装在Mac上)编译,然后在终端中执行。当使用 int do 定义变量 s &
我用 a-videosphere 制作了一个 a-scene。我尝试使用按钮启用/禁用声音,但有些想法不起作用?这是我的代码: var gargamel = 0; function
我正在使用 ISAAC 实现来生成随机整数。我需要用这些整数创建一个高斯值。首先,我需要将它们从 0 更改为 1 的 double 值。我怎样才能在Java中做到这一点?这是到目前为止我将整数转换为
我将 0x0000 到 0x01c2 范围内的十六进制值从 BLE 获取到我的手机 a 作为字符串。为了将其绘制在图表中,我必须将其转换为 double,我已经尝试过 this method但遗憾的是
我有一个父类(super class) Animal和一个子类 Dog 。在第三节课中,我有一个 List它同时接受子类型和父类(super class)型对象。 public class foo{
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 6 年前。 Improve this ques
我正在尝试查询我的用户的距离。我可以用这段代码做到这一点 PFGeoPoint.geoPointForCurrentLocationInBackground { (geoPoint: PFGe
考虑示例:http://jsfiddle.net/KWLu7/16/ 我正在尝试将总体重要性值计算为每个选定选择重要性的总和乘以其父标准重要性: var watch = $scope.$watch("
这个问题在这里已经有了答案: Bounding generics with 'super' keyword (6 个答案) 关闭 2 年前。 我有一个列表装饰器,它应该允许从一个列表转换到另一个列表
为什么下面的代码没有选择最近父类(super class)型的隐式 val? class A class B extends A trait TC[-T] { def show(t: T): Stri
这是我想要做的 def merge[A, B, C](eithers: Either[A,B]*)(implicit ev1: A x, x => x)) 关于scala - 推断常见的父类(s
我正在尝试从具有 double 类型列的Cassandra表中获取 double 值。我已经使用CQL3语法创建了表: CREATE TABLE data_double ( datetime
是否应该在不需要显式类型定义的情况下编译以下 this ? def prepList[B >: A](prefix: PlayList[B]) : PlayList[B] = prefix.fol
我正在查看某人的代码,并且在创建结构时使用了 abstract type AbstractFoo end julia> struct Foo1 struct Foo2 foo_op(x::Abst
一些示例代码: public class Main { class SomeType { } class A { protected T createSome
是否可以只接受类的泛型类型的父类(super class)型? 我正在寻找的是这样的: class MyClass { public void myMethod(TS someObject
在我的代码中,我有许多 ArrayList 被传递到排序方法中。每个 ArrayList 都有不同的泛型类型,但所有这些类型都是 Sorter 的实现。排序方法旨在接受 Sorter 类型的 Arra
如果已经有人问过这个问题,请链接并关闭这个问题。 我目前正在为另一个使用起来复杂得多(并且有潜在危险)的 API 的简化 API 设计原型(prototype)。 考虑到相关的有点复杂的对象创建,我决
我正在尝试构建一个具有某些依赖项的 android 应用程序,但是其中一个导致了此错误: Illegal class file: Class module-info is missing a supe
我是一名优秀的程序员,十分优秀!