这可能是一个广泛的问题,但最近我想知道以下内容:在我们的C#后端,我们有很多地方将一些代码包装在try
/ catch
块中,特别是调用外部WcF服务。其中一些调用对于应用程序至关重要,因此在catch块中我们记录错误并重新抛出,如:
catch(Exception ex)
{
_logger.Error("Some good error message");
throw ex;
}
另一方面,我们允许失败的服务,但我们仍然想记录错误,所以它们看起来像:
catch(Exception ex)
{
_logger.Error("Some good error message");
}
现在阅读团队成员的代码,我不能确定他们是否忘记投掷或者这是否是预期的行为。
问:有没有办法,分别是。什么是默认方式,明确地不重新抛出(不在代码中包含注释)。
我考虑过这样的事情:
catch(Exception ex)
{
_logger.Error("Some good error message");
NotThrowingHereOnPurpose();
}
// ...
// and further below a private method
// ...
private void NotThrowingHereOnPurpose(){}
答案 0 :(得分:3)
这里可能有用的一种方法是更改调用您明确允许失败的代码的方式,使其看起来根本不像try
/ catch
块
例如,您可以编写一个执行错误报告的辅助方法,并使用表达为lambdas的操作来调用它:
void InvokeFailSafe(Action action, Action<Exception> onFailure = null) {
try {
action();
} catch (Exception e) {
if (onFailure != null) {
onFailure(e);
}
}
}
现在代替try
/ catch
,你会写下这个:
InvokeFailSafe(
() => {
... The code that may fail
}
, exception => _logger.Error("Some good error message: {0}", exception)
);
或者像这样,如果你不想记录任何东西:
InvokeFailSafe(
() => {
... The code that may fail
}
);
如果您以这种方式编写代码,那么对于缺少throw
语句就毫无疑问。
答案 1 :(得分:1)
这是对dasblinkenlight的回答的相反解决方案。而不是通知别人不能重新抛出异常,而是说它必须是。
如果您只想记录它,请照常使用Error
方法。否则,您可以为记录器编写扩展方法以记录并抛出异常。
该方法将获取catched异常并使用ExceptionDispatchInfo
类重新抛出它。 ExceptionDispatchInfo
用于使用原始堆栈跟踪信息和Watson信息重新抛出异常。它的行为类似于throw;
(没有指定的异常)。
public static void ErrorAndThrow(this ILogger logger, string message, Exception exception)
{
var exceptionInfo = ExceptionDispatchInfo.Capture(exception);
logger.Error(message);
exceptionInfo.Throw();
}
并以这种方式使用它:
try
{
}
catch (Exception ex)
{
// ex would be rethrown here
_logger.ErrorAndThrow("Some good error message", ex);
}
答案 2 :(得分:0)
问:有没有办法,分别是。什么是默认方式,明确表示NOT 重新抛出(不包括代码中的注释)。
理想的方法不是捕获一般异常。现在,扔或不完全取决于你的情况。您需要了解在发生异常时知道如何处理时使用异常处理。因此,只应处理特定的例外情况。在不知道您捕获的内容的情况下捕获异常将改变应用程序的行为。
现在阅读团队成员的代码我不能确定他们是否忘记了 扔或如果这是预期的行为。
这是代码作者可以向您解释的内容。但这是一个学习从这里学习。您的代码应该是自我解释的。在您无法使用代码表达自己的特定情况下,请添加有意义的评论。
您可以查看此link以便更好地理解。
答案 3 :(得分:0)
我实际上找到了另一种方式,包括其他人在此处提出的建议,但使用内置功能:例外过滤器。我可以自由修改here中给出的示例来说明这一点:
public void MethodThatFailsSometimes()
{
try {
PerformFailingOperation();
}
catch (Exception e) when (e.LogAndBeCaught())
{
}
}
然后可以在Exception
上设置两个扩展方法,比如LogAndBeCaught
和LogAndEscape
,如下所示:
public static bool LogAndBeCaught(this Exception e)
{
_logger.Error(@"Following exception was thrown: {e}");
return true;
}
public static bool LogAndEscape(this Exception e)
{
_logger.Error(@"Following exception was thrown: {e}");
return false;
}
答案 4 :(得分:-1)
这不应该经常出现。考虑
string WebGreeting()
{
try
{
return _greetingService.HelloWorld();
}
catch(Exception ex)
{
_logger.Error("Some good error message");
//throw; // when this is missing, you get the compiler error "not all paths ..."
}
// unless you very deliberately code the on-error case
// return "nothing";
}
这样就留下了奇怪的void
方法。但这真的是你的问题吗?