要求通用方法在FAIL上引发特定的异常类型
是的,我知道我完全会和这个白痴在一起,但今天早上我的大脑还没动弹。
我想拥有一种方法,我可以说"如果情况不好,请返回这种类型的异常",对吗?
例如,类似的东西(这不起作用):
static ExType TestException<ExType>(string message) where ExType:Exception { Exception ex1 = new Exception(); ExType ex = new Exception(message); return ex; }
现在令我困惑的是,我们知道由于where子句,泛型类型将成为Exception类型。但是,代码失败,因为我们无法将Exception隐式转换为ExType。我们也不能显式转换它,例如:
static ExType TestException<ExType>(string message) where ExType:Exception { Exception ex1 = new Exception(); ExType ex = (ExType)(new Exception(message)); return ex; }
那样也失败了。那么这种事情可能吗?我有一种很强烈的感觉,那就是它真的很简单,但是我对旧的头皮却很不满意,所以要给我一些放松:P
更新
谢谢你们的回应,看来我不是个白痴! ;)
好的,所以Vegard和Sam使我进入了可以实例化正确类型的地步,但随后显然卡住了,因为消息参数在实例化之后是只读的。
Matt的回应打在了头上,我已经测试过了,一切都很好。这是示例代码:
static ExType TestException<ExType>(string message) where ExType:Exception, new () { ExType ex = (ExType)Activator.CreateInstance(typeof(ExType), message); return ex; }
甜的! :)
谢谢你们!
解决方案
回答
我们是否尝试过:
static T TestException<Exception>(string message) {}
因为我感觉到没有必要放入泛型约束,因为所有可抛出的异常都必须继承自System.Exception。
请记住,泛型确实接受继承的类型。
回答
我认为所有异常都应该具有无参数的构造函数,并具有Message属性,因此以下内容应该起作用:
static ExType TestException<ExType>(string message) where ExType:Exception { ExType ex = new ExType(); ex.Message = message; return ex; }
编辑:好的,消息是只读的,因此我们必须希望该类改为实现Exception(string)构造函数。
static ExType TestException<ExType>(string message) where ExType:Exception { return new ExType(message); }
回答
我们几乎可以这样做:
static void TestException<E>(string message) where E : Exception, new() { var e = new E(); e.Message = message; throw e; }
但是,由于Exception.Message是只读的,因此无法编译。只能通过将其传递给构造函数来进行分配,并且除了默认构造函数之外,没有其他方法可以约束泛型类型。
我认为我们必须使用反射(Activator.CreateInstance)来"新建"带有message参数的自定义异常类型,如下所示:
static void TestException<E>(string message) where E : Exception { throw Activator.CreateInstance(typeof(E), message) as E; }
Edit Oops刚意识到我们要返回异常,而不是抛出异常。同样的原则适用,因此我将使用throw语句保持原样。
回答
解决方案的唯一问题是可以创建Exception的子类,该子类不使用单个字符串参数实现构造函数,因此可能引发MethodMissingException。
static void TestException<E>(string message) where E : Exception, new() { try { return Activator.CreateInstance(typeof(E), message) as E; } catch(MissingMethodException ex) { return new E(); } }