Try Catch错误处理的最佳实践

时间:2010-08-06 19:10:39

标签: .net exception exception-handling

我试图避免在捕获时返回不正确的值,但我找不到比这更好的解决方案:

    private SecurityLevel ApiGetSecurityLevel()
    {
        try
        {
            return _BioidInstance.GetSecurityLevel();
        }
        catch
        { 
            return SecurityLevel.High;
        }
    }

有没有更好的方法这样做,所以我不会返回错误的值?我无法更改SecurityLevel枚举。

11 个答案:

答案 0 :(得分:12)

不要抓住异常。允许异常“冒泡”以强制调用者/调用者处理设置默认安全值。


如果您确实想要返回值,请使用Nullable<SecurityLevel>SecurityLevel?

private SecurityLevel? ApiGetSecurityLevel() { 
    try { 
        return _BioidInstance.GetSecurityLevel(); 
    } 
    catch {  
        return null; 
    } 
} 

然后用作:

if (ApiGetSecurityLevel().HasValue == false) {
    // use default security level
}

答案 1 :(得分:6)

这可能是应用程序失败的情况吗?也就是说,如果无法确定SecurityLevel,那么用户应该无法继续?

如果是这样,为什么不重新抛出并让UI处理它(或让它记录下来,但是你的商店有效)?

如果应用程序应该能够继续,请选择(并记录)一些默认值并完成您正在做的事情。

答案 2 :(得分:5)

首先,只要GetSecurityLevel返回SecurityLevel,就没有理由尝试/捕获。编译器会在那里发现任何问题。

其次,这不是一个很好用的try / catch。 Try / catch不应该用于正常的控制流程,仅适用于特殊情况。

如果出于某种原因,GetSecurityLevel()不返回SecurityLevel枚举类型:

private SecurityLevel ApiGetSecurityLevel()
    {
        object securityLevel = _BioidInstance.GetSecurityLevel();
        if (securityLevel is SecurityLevel)
        {
             return _BioidInstance.GetSecurityLevel();
        }
        else
        {
             throw new Exception("Invalid SecurityLevel");
        }
    }

答案 3 :(得分:2)

如果你可以改变fonction的返回类型,我会将它改为可以为空的枚举,并在catch中返回null。

private SecurityLevel? ApiGetSecurityLevel()
{
    try
    {
        return _BioidInstance.GetSecurityLevel();
    }
    catch
    { 
        return null;
    }
}

答案 4 :(得分:1)

你可以返回Nothing。并使你的函数看看结果,如果不是ApiGetSecurityLevel()是什么

答案 5 :(得分:1)

你可以让异常冒泡。

答案 6 :(得分:1)

除了马特的回答,让异常发生的错误是什么?如果您的应用程序中存在某些状态或访问无效状态,那么将其杀死可能会更好。

答案 7 :(得分:0)

public class BioId { public SecurityLevel SecLevel { get; set; } }

private bool ApiGetSecurityLevel(BioId bioId)
{
    try
    {
        bioIdSecLevel = bioId.GetSecurityLevel();
        return true;
    }
    catch (PossibleException)
    {
        return false;
    }
}

然后将它与if一起使用,如果它返回false,则让处理代码决定它的BioId的默认安全级别。

虽然我同意其他所有人的意见,但实际上你只想让异常泡泡让顶层处理它们。虽然有时会有标准不让异常泡沫,因为它们泡过的每一层都显然会达到性能,但我说你不应该有太多的层,洋葱很复杂,就像食人魔。

答案 8 :(得分:0)

如果您可以向Nothing添加NotSet / SecurityLevel枚举,则可以从catch块返回该枚举。当你无法确定它们时,返回升级的私有是一个非常奇怪的选择。

或者,将SecurityLevel作为可为空的枚举返回。

private SecurityLevel? ApiGetSecurityLevel()
{
    try
    {
        return _BioidInstance.GetSecurityLevel();
    }
    catch
    { 
        return null;
    }
}

答案 9 :(得分:0)

SecurityLevel sec = _BioidInstance.GetSecurityLevel();
return (Enum.IsDefined(Typeof(SecurityLevel), sec) ? sec : SecurityLevel.High);

如果它在枚举中定义,它将返回_BioidInstance中的安全级别,否则它将返回SecurityLevel.High。

如果是我,如果我知道安全级别不能超出枚举中定义的内容,那么我会在没有try-catch的情况下执行,如果涉及到它就让它失败。这样我知道其他地方出了问题,我可以去解决它。

答案 10 :(得分:0)

在这种情况下,安全性变为二进制。

要使用安全化合物的一个例子,在门口有人可以进入或不能进入。如果他们没有达到安全级别,那个人就不应该通过大门。

如果GetSecurityLevel()方法抛出异常,则会在门口拒绝某些内容。然后授予一些任意安全级别并允许它们通过不是一个好主意。

我会彻底废除这种方法,并用更接近

的东西替换它
private bool HasSecurityLevel(SecurityLevel securityLevel) 
{ 
    try 
    { 
        return _BioidInstance.GetSecurityLevel() == securityLevel; 
    } 
    catch 
    {  
        return false; 
    } 
} 

然后根据需要检查每个安全级别。

这种情况的合理性在某种程度上必须进行检查,也可以使其尽可能接近源(当首次获得安全级别时)。