Обработка класса, который не выдает исключение в C # - PullRequest
1 голос
/ 04 августа 2010

У меня есть некоторый код пользовательского интерфейса, который выглядит следующим образом:

try
{
    SomeClass classInstance = new SomeClass(someId);
}
catch (Exception exception)
{
    // Content wasn't created, show a message, stop processing
    return;
}

Кажется, что был добавлен try catch, потому что конструктор для SomeClass сработал бы, если получаемый им someId был бы недействительным, иданные не могут быть найдены в БД.

Запустив этот код через FXCop недавно, он предупреждает против использования общего исключения, но все, что делает SomeClass, - это генерирует новое исключение с сообщением о том, что оно не удалось инициализировать.

Полагаю, проблема в том, что конструктор класса должен иметь свое собственное исключение, которое я мог бы затем обработать в своем пользовательском интерфейсе, но мне интересно, что еще я мог бы сделать с кодом выше, чтобы обработать исключение, которое соответствуетТребования FXCop?

Ответы [ 6 ]

4 голосов
/ 04 августа 2010

Правило FxCop существует, потому что вышеприведенный блок catch (Exception) перехватывает все возможные исключения, включая исключения низкого уровня, такие как StackOverflowException, которые вы, вероятно, не можете отловить полезным способом.

Правильный подход определеннобросить более конкретный тип: либо тот, который вы изобрели, либо существующий тип исключения платформы .NET, который точно соответствует вашей ситуации.(Если вы сомневаетесь, я обычно обращаюсь к InvalidOperationException.)

В качестве альтернативы, вы можете проверить точный тип исключения при его обнаружении.Это не предотвратит предупреждение FxCop, но должно устранить основную проблему:

catch (Exception exception)
{
    if (exception.GetType() == typeof(Exception))
    {
        // Content wasn't created, show a message, stop processing
        return;
    }
    else
    {
        // Some other exception type that wasn't thrown from our code -
        //    delegate to a higher-level exception handler
        throw;
    }
}
3 голосов
/ 04 августа 2010

Вам не нужно исключение custom ; просто используйте одну из десятков, которые уже существуют в рамках для определенных обстоятельств. Если someId это плохо, бросьте ArgumentException - для этого он и создан. Если что-то равно нулю, чего не должно быть, произойдет NullReferenceException; просто пусть это будет брошено. И т. Д. Бросать простой Exception - все равно, что сказать "что-то пошло не так - прочитайте сообщение для деталей", а не "это пошло не так".

FxCop жалуется на catch (Exception), потому что слишком часто злоупотребляют, чтобы проглотить все исключения, а не позволять им распространяться и обрабатываться кодом, который знает, как это сделать. Вы должны быть в состоянии сказать, какие типы исключений выбрасываются, и перехватывать их, позволяя тем, кого вы не знаете, пробраться вверх по стеку вызовов.

2 голосов
/ 04 августа 2010

Вы должны исправить конструктор класса. Бросок Exception - это никогда хорошая идея.

Однако, чтобы обойти проблему, которая возникла у вас временно (поскольку это ужасный, ненадежный взлом), вы можете сравнить сообщение об исключении с ожидаемым:

catch (Exception exception)
{
    if (exception.Message == "whatever your class sets the message to")
        // Content wasn't created, show a message, stop processing
        return;
    else
        // Any other exception should bubble
        throw;
}
0 голосов
/ 04 августа 2010

Как говорили многие другие, конструктор не должен бросать голую Exception.Видя, что конструктор извлекает данные из БД и выдает их на основе результата, лучшим решением будет создание собственного класса исключений.

Создание исключений в Visual Studio очень просто.Просто введите Exception и нажмите TAB .Затем он создаст класс исключения с необходимыми конструкторами (все четыре).Не бойтесь создавать классы, которые мало что делают, для этого они и предназначены.

Вот как я написал бы этот класс:

public class SomeClass {
    public SomeClass(int someId) {
        if (someId < 0) //validation on the ID, can it be negative?
            throw new ArgumentException("someId", "ID cannot be negative");

        //Perform DB operation
        if (/*DB error - not found*/)
            throw new DataNotFoundException("Cannot find record with ID " + someId);
    }
}

[Serializable]
public class DataNotFoundException : Exception {
    public DataNotFoundException() { }
    public DataNotFoundException(string message) : base(message) { }
    public DataNotFoundException(string message, Exception inner) : base(message, inner) { }
    protected DataNotFoundException(
      System.Runtime.Serialization.SerializationInfo info,
      System.Runtime.Serialization.StreamingContext context)
        : base(info, context) { }
}
0 голосов
/ 04 августа 2010

Если FXCop не нравится обрабатывать общее исключение (и я склонен согласиться), то, возможно, у вас есть доступ к исходному коду SomeClass. Измените конструктор, чтобы генерировать исключение, которое является более конкретным, например, ArgumentOutOfRangeException или какое-то пользовательское исключение.

В этом случае ваш код будет выглядеть следующим образом:

try
{
   SomeClass classInstance = new SomeClass(someId);
}
catch(ArgumentOutOfRangeException exception)
{
   // Content wasn't created, show a message, stop processing
   return;
}
0 голосов
/ 04 августа 2010

Использование InvalidOperationException вместо броска Exception звучит так, как будто это разумно.

...