Лучшая практика для обработки ошибок при попытке захвата

Я пытаюсь избежать возврата неправильного значения, когда в catch, но у меня возникают проблемы с поиском лучшего решения, чем это:

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

Есть ли лучший способ сделать это, чтобы я не возвращал неверные значения? Я не могу изменить перечисление SecurityLevel.

Ответ 1

Не поймайте исключение. Разрешить исключение "bubble-up", чтобы заставить вызывающего/вызывающего абонента обрабатывать значение по умолчанию для безопасности.


Если вы действительно хотите вернуть значение, используйте Nullable<SecurityLevel> или SecurityLevel?.

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

Затем используйте как:

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

Ответ 2

Возможно ли, что это случай, когда приложение должно просто потерпеть неудачу? То есть, если SecurityLevel не может быть определен, пользователь не сможет продолжить?

Если да, почему бы просто не повторить бросок и не позволить UI обрабатывать его (или позволить ему регистрироваться, однако ваш магазин работает)?

Если приложение должно продолжить, выберите (и запишите) значение по умолчанию и сделайте то, что вы делаете.

Ответ 3

Во-первых, нет причин для этого try/catch, пока 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");
        }
    }

Ответ 4

Если вы можете изменить тип возврата для fonction, я поменяю его на нулевое перечисление и возвращу null в catch.

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

Ответ 5

Ты можешь вернуть Ничего. И заставьте вашу функцию смотреть на результат, как если бы не ApiGetSecurityLevel() ничего не было

Ответ 6

Вы можете просто позволить пузырю всплывать.

Ответ 7

В дополнение к ответу Мэтта, что случилось с допуском исключения? Если есть некоторая недействительность состояния или доступ в вашем приложении, вероятно, было бы лучше просто убить его.

Ответ 8

Вы можете обернуть его внутри одного из своих собственных перечислений и перевести их на свой. Тогда ваш может содержать "недопустимый" уровень безопасности, и вы избегаете использования типов blackboxed.

Ответ 9

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.

Хотя я согласен со всеми остальными, что по практичности вы хотите просто позволить пузырьку исключений и позволить верхним уровням обрабатывать их. Хотя иногда есть стандарты, чтобы не допускать пузырей исключения, потому что каждый слой, который они пузыряют, может, по-видимому, поражать производительность, но к этому я говорю, что у вас не должно быть слишком много слоев, лук сложный, например, огры.

Ответ 10

Если вы можете добавить перечисление Nothing/NotSet в SecurityLevel, то вы можете вернуть это из блока catch. Возвращение эскалированных привалов, когда вы не можете их определить, действительно странный выбор.

В качестве альтернативы верните SecurityLevel как нулевое перечисление.

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

Ответ 11

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

Он вернет уровень безопасности в _BioidInstance, если он определен в перечислении, иначе он вернет SecurityLevel.High.

Если бы это был я, если бы я знал, что уровень безопасности не может быть чем-либо вне того, что определено в перечислении, я просто обойдусь без try-catch и дайте ему потерпеть неудачу, если дело дойдет до него. Таким образом, я знаю, что что-то еще где-то пошло не так, и я могу исправить это.

Ответ 12

В этом случае защита становится двоичной.

Чтобы использовать пример безопасного соединения, у ворот либо кто-то может попасть, либо не может. Если они не смогут получить уровень безопасности, этот человек не должен пройти через ворота.

Если метод GetSecurityLevel() выдает исключение, что-то было отвернуто у ворот. Чтобы затем предоставить некоторый произвольный уровень безопасности и разрешить им это не очень хорошая идея.

Я полностью покончил с этим методом и заменил бы его чем-то ближе к

private bool HasSecurityLevel(SecurityLevel securityLevel) 
{ 
    try 
    { 
        return _BioidInstance.GetSecurityLevel() == securityLevel; 
    } 
    catch 
    {  
        return false; 
    } 
} 

а затем проверьте каждый уровень безопасности по мере необходимости.

Рациональное для этого - в какой-то момент проверка должна быть сделана, может также сделать ее как можно ближе к источнику (при первом получении уровня безопасности).