MSt*_*odd 6 c# error-handling exception-handling
我看过,但找不到一些关于我的异常问题的明确答案,特别是关于C#最佳实践.
也许我总是对使用异常的最佳方式感到困惑,我跑过这篇文章,基本上说'总是使用异常,从不使用错误代码或属性' http://www.eggheadcafe.com/articles/20060612.asp.我肯定会买,但这是我的困境:
我有一个函数'caller',它调用'callee'.'callee'执行一些不同的操作,每个操作都可能抛出相同类型的异常.如何将有意义的信息传回"调用者",了解"被调用者"在异常时正在做什么?
我可以抛出一个像下面这样的新异常,但我担心我会搞乱堆栈跟踪这是坏事:
//try to log in and get SomeException
catch(SomeException ex)
{
throw new SomeException("Login failed", ex);
}
...
//try to send a file and get SomeException
catch(SomeException ex)
{
throw new SomeException("Sending file failed", ex):
}
Run Code Online (Sandbox Code Playgroud)
谢谢,马克
没有单一的最佳实践来涵盖.Net中的所有场景.任何说"总是使用例外"或"总是使用错误代码"的人都是错误的.用.Net编写的程序是广泛而复杂的,可以概括为类似的硬性规则.
在许多情况下,例外情况根本不合适.例如,如果我有一个非常紧密的循环查找值,Dictionary<TKey, TValue>我绝对更喜欢TryGetValue投掷索引器.然而在其他情况下,如果提供给我的数据已经签约已经在地图中,我宁愿抛出.
处理此决定的最佳方式是逐案处理.一般来说,如果情况真的特殊,我只使用例外.一个基本上是呼叫者无法预测的或来自呼叫者的结果明确违反合同.例子
调用者不需要知道被调用者在异常时正在做什么.它不应该知道被调用者是如何实现的.
在这样的场景中,我通常注入一个记录器并记录特定错误并重新抛出原始异常:
//try to log in and get SomeException
catch(SomeException ex)
{
logger.LogError("Login failed");
throw;
}
...
//try to send a file and get SomeException
catch(SomeException ex)
{
logger.LogError("Sending file failed");
throw;
}
Run Code Online (Sandbox Code Playgroud)
这throw;将使原始堆栈跟踪保持活动状态(而不是throw ex;创建新的堆栈跟踪)。
编辑
根据您的实际代码正在执行的操作,实际分解callee为多个调用(Login()、SendFile()等)可能是有意义的,因此caller执行各个步骤而不是调用一个执行所有操作的大方法。然后调用者将知道失败的位置并可以采取行动(可能会要求用户提供不同的登录凭据)