我想知道如何决定:
1)如果要抛出自定义异常或
2)返回一种LOG对象,其中包含'CityNotFound','ReferenceConstraintBroken'等标志。
我一直在阅读例外是昂贵的。如果我只需要知道过程结果的具体细节,对我来说,拥有一个只包含过程的必要信息的自定义“过程LOG对象”听起来更有益。
所以,如果我回到 我的问题 :
什么时候最好抛出一个异常,何时更好地返回一些错误日志'object'?
答案 0 :(得分:15)
抛出异常以提供更多信息(异常类型,消息等)以便正确处理并表示:
我实际上不鼓励返回“日志对象”(即返回异常对象而不是抛出一个),因此
if
语句不必要的混淆,以检查结果并处理潜在错误
out
参数),否则你不能“冒泡”错误/异常进行范围处理,导致进一步的限制如果你想返回“日志对象”,你应该使用布尔返回值和有意义的方法(即FindCity
)或带有out
布尔参数的方法(即TryFindCity
)。这样,您不需要指定标志,只需使用其布尔返回允许您确定将要标志值的方法。
修改强>
根据OP的评论,如果有一个巨大的方法有许多可能的验证错误,那么应该重构巨大的方法来调用每个抛出适当异常的较小方法。然后,巨大的方法可以简单地重新抛出每个异常,或者只是让每个异常冒出来,如果它不应该是处理它的那个异常。
如果存在阻止“正确分离”的验证依赖项,则只需使用正确的参数抛出一个ValidationException
。下面是这个课程的一个例子:
public class ValidationException : Exception {
private readonly object _Field;
public object Field { get { return _Field; } }
public ValidationException(string message) : base(message) { }
public ValidationException(string message, object field)
: this(message) {
_Field = field;
}
}
然后你可以抛出一个解释验证错误的异常。
答案 1 :(得分:5)
如果您担心异常的性能,可以考虑“测试人员”模式,在大多数情况下可以用它来避免它们(它还使代码比try / catch中的更具可读性)我的意见)。
// Traditional try catch
try
{
var record = myDb.myTable.Select(primaryKey);
// do something with record...
}
catch (RecordNotFoundException)
{
// The record not found in the database... what to do?
}
// Tester-doer pattern
if (myDb.myTable.RecordExists(primaryKey))
{
var record = myDb.myTable.Select(primaryKey);
// do something with record...
}
else
{
// The record not found in the database... what to do?
}
同样的结果,没有例外。成本是你必须自己编写“RecordExists”函数,通常它就像做返回COUNT FROM myTable WHERE PrimaryKey = foo == 1
这样简单答案 2 :(得分:3)
略微转过头来。考虑一下,我是否知道如何在函数中处理这个条件,并且代码会被频繁调用以使其值得一试,或者更一般地说,这是非常特殊的吗?
如果在您的函数的例程操作中出现这种情况,则将其作为返回值的一部分进行处理。如果因为您的函数被滥用或某些资源不可用而发生抛出异常。
答案 3 :(得分:2)
如果调用者可以阻止异常(比如知道该城市不存在),则抛出异常。否则返回错误。
我永远不会返回log
个对象。它使代码不可读,因为你必须在任何地方添加if
语句和特殊处理。最好添加CheckIfCityExists
等方法。
答案 4 :(得分:1)
一般来说,只有在出现绝对意外的情况时才会返回异常。如果你知道并且可能发生这种情况,那么你应该尝试通过发送错误代码来处理它,或者更好地处理它,将代码格式化为较小的片段,
实施例