声明一种方法总是会引发异常?
-
28-09-2019 - |
题
我有一个类似...的方法
int f() {
try {
int i = process();
return i;
} catch(Exception ex) {
ThrowSpecificFault(ex);
}
}
这会产生编译器错误,“并非所有代码路径返回值”。但是在我的情况下,抛出特定福特()将始终抛出(适当的)例外。因此,我被迫在结尾处提出回报率,但这很丑陋。
首先,这种模式的目的是因为“ process()”是对外部Web服务的调用,但需要翻译各种不同的异常以匹配客户端的预期接口(我想〜位置模式)。
有什么干净的方法吗?
解决方案
我建议你转换 ThrowSpecificFault(ex)
到 throw SpecificFault(ex)
;这 SpecificFault
方法将返回要抛出的异常对象而不是抛出它。更干净。
这是推荐的模式 微软的指南 (找到文本“使用异常构建器方法”)。
其他提示
现在,返回类型可以是一种类型,也可以是“无返回类型”的“ void”。从理论上讲,我们可以添加第二种特殊返回类型“ Never”,它具有您想要的语义。表达式陈述的终点是由“永不”返回方法组成的呼吁,将被认为是无法达到的,因此,在C#中的每个情况下,“ goto”,“ throw”或“ return”是合法的。 。
现在不太可能将其添加到现在的类型系统中,十年。下次您从头开始设计类型系统时,请记住包含“ Never”类型。
这里的问题是,如果您进入 catch
块IN f()
您的功能将永远不会返回值。这将导致错误,因为您将功能声明为 int
这意味着您告诉编译器您的方法将返回整数。
以下代码将执行您要寻找的内容,并始终返回整数。
int f() {
int i = 0;
try {
i = process();
} catch(Exception ex) {
ThrowSpecificFault(ex);
}
return i;
}
将返回语句放在函数末尾,您会没事的。
无论您的应用程序经历什么执行路径,确保您的方法始终返回值总是一个好主意。
您可以这样做:
catch (Exception ex)
{
Exception e = CreateSpecificFault(ex);
throw e;
}
不。
想象一下 ThrowSpecificFault
在单独的DLL中定义。如果您修改DLL以不引发异常,然后在不重新编译的情况下运行程序,会发生什么?
您有三个选择:
总是返回我,但会预先调理:
int f() {
int i = 0; // or some other meaningful default
try {
i = process();
} catch(Exception ex) {
ThrowSpecificFault(ex);
}
return i;
}
从该方法中返回例外,并抛出:
int f() {
try {
int i = process();
return i;
} catch(Exception ex) {
throw GenerateSpecificFaultException(ex);
}
}
或创建一个自定义异常类,然后抛出:
int f() {
try {
int i = process();
return i;
} catch(Exception ex) {
throw new SpecificFault(ex);
}
}
怎么样:
int f() {
int i = -1;
try {
i = process();
} catch(Exception ex) {
ThrowSpecificFault(ex);
}
return i;
}
是的。
不要指望throwspecificfault()会引发异常。让它返回例外,然后将其扔在这里。
实际上,这也更有意义。您不使用“正常”流程的异常,因此,如果您每次都引发异常,则例外将成为规则。在功能中创建特定的异常,然后将其扔在此处,因为它是此处流的例外。
我想您可以使throwspecificfault返回对象,然后您可以
return ThrowSpecificFault(ex)
否则,您可以将throwsefificfault重写为异常子类型的构造函数,也可以将throwspecificfault放入创建异常但不会抛出它的工厂中。
在您的情况下,这是您的知识不是编译器。现在可以说这种方法肯定会引发一些讨厌的例外。
试试这个
int f() {
try {
return process();
} catch(Exception ex) {
ThrowSpecificFault(ex);
}
return -1;
}
您也可以使用掷键字
int f() {
try {
return process();
} catch(Exception ex) {
throw ThrowSpecificFault(ex);
}
}
但是,该方法应返回一些例外,而不是抛出它。
使用Unity.therception清理代码。通过拦截处理,您的代码看起来像这样:
int f()
{
// no need to try-catch any more, here or anywhere else...
int i = process();
return i;
}
下一步您需要做的就是定义拦截处理程序,您可以自定义裁缝以进行例外处理。使用此处理程序,您可以处理应用程序中所有异常。好处是,您不再需要使用TryCatch块标记所有代码。
public class MyCallHandler : ICallHandler, IDisposable
{
public IMethodReturn Invoke(IMethodInvocation input,
GetNextHandlerDelegate getNext)
{
// call the method
var methodReturn = getNext().Invoke(input, getNext);
// check if an exception was raised.
if (methodReturn.Exception != null)
{
// take the original exception and raise a new (correct) one...
CreateSpecificFault(methodReturn.Exception);
// set the original exception to null to avoid throwing yet another
// exception
methodReturn.Exception = null;
}
// complete the invoke...
return methodReturn;
}
}
可以通过配置文件或以编程方式将类注册到处理程序。代码相当简单。注册后,您可以使用统一实例化对象,例如:
var objectToUse = myUnityContainer.Resolve<MyObjectToUse>();
有关统一的更多信息: