声明一个方法总是抛出一个exception?

我有一个像……的方法

int f() { try { int i = process(); return i; } catch(Exception ex) { ThrowSpecificFault(ex); } } 

这会产生编译器错误,“并非所有代码路径都返回值”。 但在我的情况下,ThrowSpecificFault()将始终抛出(相应的)exception。 所以我被迫在最后放一个返回值,但这很难看。

首先,这种模式的目的是因为“process()”是对外部Web服务的调用,但需要转换各种不同的exception以匹配客户端的预期接口(我认为是〜外观模式)。

有任何更干净的方法吗?

我建议你转换ThrowSpecificFault(ex)throw SpecificFault(ex) ; SpecificFault方法将返回要抛出的exception对象而不是抛出它本身。 更清洁。

这是Microsoft指南推荐的模式(查找文本“使用exception构建器方法”)。

这里的问题是,如果你进入f()catch块你的函数永远不会返回一个值。 这将导致错误,因为您将函数声明为int ,这意味着您告诉编译器您的方法将返回一个整数。

以下代码将执行您要查找的内容并始终返回一个整数。

 int f() { int i = 0; try { i = process(); } catch(Exception ex) { ThrowSpecificFault(ex); } return i; } 

将return语句放在函数的末尾,你会没事的。

无论应用程序通过什么执行路径,确保您的方法始终返回值始终是一个好主意。

现在返回类型可以是类型,或“void”意味着“无返回类型”。 理论上我们可以添加第二个特殊的返回类型“never”,它具有你想要的语义。 包含对“never”返回方法的调用的表达式语句的结束点将被视为无法访问,因此在C#中的每个上下文中都是合法的,其中“goto”,“throw”或“return”是合法的。

十年后,这种类型系统不太可能被添加到类型系统中。下次从头开始设计类型系统时,请记住包含“从不”类型。

没有。

想象一下,如果ThrowSpecificFault是在一个单独的DLL中定义的。 如果你修改DLL不抛出exception,那么运行你的程序而不重新编译它会发生什么?

你可以这样做:

 catch (Exception ex) { Exception e = CreateSpecificFault(ex); throw e; } 

你有三个选择:

总是返回我但预先声明它:

 int f() { int i = 0; // or some other meaningful default try { i = process(); } catch(Exception ex) { ThrowSpecificFault(ex); } return i; } 

从方法返回exception并抛出:

 int f() { try { int i = process(); return i; } catch(Exception ex) { throw GenerateSpecificFaultException(ex); } } 

或者创建一个自定义的Exception类并抛出:

 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()抛出exception。 让它返回exception,然后把它扔到这里。

它实际上也更有意义。 您不对“正常”流使用exception,因此如果每次都抛出exception,则exception成为规则。 在函数中创建特定的exception,并将其抛在此处,因为它是流程的一个例外。

我想你可以让ThrowSpecificFault返回一个Object,然后就可以了

 return ThrowSpecificFault(ex) 

否则,您可以将ThrowSpecificFault重写为Exception子类型的构造函数,或者您可以将ThrowSpecificFault设置为创建exception但不抛出exception的工厂。

在你的情况下,但这是你的知识而不是编译器。 现在可以说这种方法肯定会引发一些令人讨厌的exception。

试试这个

 int f() { try { return process(); } catch(Exception ex) { ThrowSpecificFault(ex); } return -1; } 

您也可以使用throw关键字

 int f() { try { return process(); } catch(Exception ex) { throw ThrowSpecificFault(ex); } } 

但是那个方法应该返回一些exception而不是扔掉它。

使用Unity.Interception清理代码。 使用拦截处理,您的代码可能如下所示:

 int f() { // no need to try-catch any more, here or anywhere else... int i = process(); return i; } 

您在下一步中需要做的就是定义一个拦截处理程序,您可以自定义exception处理。 使用此处理程序,您可以处理应用程序中引发的所有exception。 好处是您不再需要使用try-catch块标记所有代码。

 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; } } 

将类注册到处理程序可以通过配置文件或以编程方式完成。 代码相当简单。 注册后,使用Unity实例化对象,如下所示:

 var objectToUse = myUnityContainer.Resolve(); 

有关Unity.Interception的更多信息:

http://msdn.microsoft.com/en-us/library/ff646991.aspx