尝试 - 赶上回归策略

时间:2011-01-20 12:07:13

标签: c# asp.net

在方法中使用try-catch时,如果您希望应用程序即使出现错误也能继续,是否可以通过catch块返回默认值作为return,并记录错误以供日后查看?< / p>

例如:

public static string GetNameById(int id)
{
    string name;
    try
    {
        //Connect to Db and get name - some error occured
    }
    catch(Exception ex)
    {
        Log(ex);
        name = String.Empty;
    }

    return name;
}

示例2:

public static string GetIdByName(string name)
{
    int id;
    try
    {
        //Connect to Db and get id- some error occured
    }
    catch(Exception ex)
    {
        Log(ex);
        id = 0;
    }

    return id;
}

是否可以返回任何默认值(取决于方法的返回类型...... ???),以便需要此方法的结果的应用程序逻辑不会崩溃并继续运行.... / p>

提前致谢...

问候。

11 个答案:

答案 0 :(得分:6)

异常处理的建议是,大多数情况下,您应该只捕获可以执行某些操作的异常(例如,重试操作,尝试不同的方法,提升安全性等)。如果您在应用程序的其他位置记录了全局级别,则不需要这种catch-log-return。

个人 - 通常 - 在这种情况下我会这样做:

public static string GetNameById(int id)
{
    string name;
    try
    {
        //Connect to Db and get name - some error occured
    }
    catch(Exception ex)
    {
        Log(ex);
        throw; // Re-throw the exception, don't throw a new one...
    }

    return name;
}

和往常一样 - 这取决于。

请注意其他陷阱,例如调用方法没有意识到存在失败,并且继续执行工作,假设抛出异常的方法实际上有效。此时,您将开始讨论“返回代码与抛出异常”,您可以在SO.com和一般的互联网上找到大量资源。

答案 1 :(得分:4)

我认为这不是一个好的解决方案。在我看来,让调用者处理异常会更好。或者,您可以捕获方法中的异常并抛出自定义异常(将捕获的异常作为内部异常)。

另一种方法是制作TryGet方法,例如:

public static bool TryGetNameById(int id, out string name) 
{ 
    try 
    { 
         //Connect to Db and get name - some error occured
         name = actualName
         return true; 
    } 
    catch(Exception ex) 
    { 
        Log(ex); 
        name = String.Empty; 
        return false;
    }  
} 

我认为这种方法更有意思揭示。方法名称本身表明它可能无法始终产生有用的结果。在我看来,这比返回一些调用者必须能够知道的正确业务逻辑的默认值更好。

答案 2 :(得分:2)

我的意见是,我永远不会将错误视为静音。

如果抛出某个异常,则应将其视为致命错误。

也许问题是抛出异常事件的异常。例如,业务验证不应该抛出这样的例外。

我更愿意验证业务并将错误转换为“损坏的规则”并将它们传输到演示文稿或任何地方,这样可以节省CPU和内存,因为没有堆栈跟踪。

另一种情况是数据连接丢失或导致应用程序处于错误状态的其他情况。然后,我更愿意记录错误并提示用户重新打开应用程序,或者应用程序可能会重新启动。

我想给你一些建议:你听说过PostSharp吗?检查一下,您可以使用AOP范例实现异常日志记录。

答案 3 :(得分:1)

建议您只捕获可以处理和恢复的错误。捕获和消耗您无法处理的异常是不好的形式。但是,某些环境/应用程序定义了违反此理想行为的严格规则。

在这些情况下,我会说如果您没有选择,您可以使用退货做您喜欢的事情 - 由您的应用程序来处理它们。

基于您的应用程序可以在尝试获取ID时处理任何类型的失败的假设,然后返回默认ID是一个足够好的选择。您可以进一步使用类似特殊情况模式的东西来返回空/丢失的对象,但对于简单的数据类型,这似乎是没有根据的。

答案 4 :(得分:0)

最好记录异常,然后重新进行修改,以便在上层正确处理。

注意:“记录异常部分”当然是可选的,并且在很大程度上取决于您的处理策略(您会在其他地方再次登录吗?)

不要让应用程序因swalowing异常而崩溃,而是让它们通过并试图找到它们首先被抛出的根本原因。

答案 5 :(得分:0)

这很大程度上取决于上下文和调用方法的设计方式。我过去常常回复默认值,因为我现在只知道这是非常错误的......

你应该想象一下catch块会抛出异常,在正确记录之后,调用方法可以有另一个try catch,并且根据错误的严重程度可以通知用户或相应的行为。

事实是,如果你返回一个空字符串,在某些情况下,可能是调用者“认为”有一个空名称的用户,而最好通知用户没有找到该记录,例如。

取决于记录器的工作方式,您可以仅在处理异常的情况下记录异常,而不是记录在所有捕获中......

答案 6 :(得分:0)

这取决于你想要什么。如果你记录异常对你来说很重要,但是其他一切都在继续,那么这就是 - 老实说 - 好吧。

另一方面:如果发生异常,您必须确保这对您的应用程序的进一步运行没有影响。

答案 7 :(得分:0)

取决于您希望自己的应用做什么...... 例如,如果在尝试连接数据库时遇到SqlException,则显示友好消息“无法登录”。

处理所有错误有时被认为是错误的,尽管人们不同意...... 您的应用程序遇到了您没有预料到的异常,您不能再100%确定您的应用程序处于什么状态,执行了哪些代码行,哪些代码行没有等等。进一步阅读:http://blogs.msdn.com/b/larryosterman/archive/2005/05/31/423507.aspx。 还有更多:http://blogs.msdn.com/b/oldnewthing/archive/2011/01/20/10117963.aspx

答案 8 :(得分:0)

try / catch的目的是让你能够在优雅的庄园中捕获和处理错误,允许应用程序继续执行,而不是简单地崩溃应用程序并停止执行。

因此,返回默认值是完全可以接受的。但是,如果返回默认值而不是导致更多错误,请确保以下所有代码都将继续运行。

例如 - 在您的示例中,如果数据库连接失败,请确保没有其他命令可以编辑/检索数据库中的值。

答案 9 :(得分:0)

真的很依赖。在大多数情况下,它不是 - 问题是如果有一个特定情景的问题,你永远都找不到。 Soemtiems恢复尝试是好的。这种规范取决于环境和实际逻辑。

“燕子和文件”真正有效的场景在普通世界中很少见,而且介于两者之间。当编写驱动程序类型的thigns时(例如加载的模块与外部系统通信),它们会更频繁地进入。返回值或默认(T)等效的maeks感觉也取决于。

我会说在99%的情况下让异常运行起来。在1%的情况下,返回一些合理的默认值可能是有意义的。

答案 10 :(得分:0)

我认为答案必须是“它取决于”。

在某些情况下,如果出现错误,可以从函数返回空字符串。如果你正在查找显示某人的地址,那么空字符串可以正常运行而不是崩溃。

在其他情况下,它可能效果不佳。例如,如果您返回一个用于安全性查找的字符串(例如getSecurityGroup),那么如果您返回错误的内容,您将会遇到非常不希望的行为,并且您最好不要抛出错误并让用户知道某些内容已经存在出错了而不是假装。

更糟糕的是,如果您持久保存用户提供给您的数据。当你获得他们的数据时出现问题,你返回默认值并存储它甚至没有告诉他们......这一定是坏事。

所以我认为您需要查看每个考虑此问题的方法,并确定抛出错误或返回默认值是否有意义。

事实上,作为一个更普遍的规则,每当你发现错误时,你应该仔细考虑它是否是一个可接受的错误并且继续是允许的,或者它是否是一个停止显示的错误,你应该放弃。

相关问题