Какие исключения я должен обработать - PullRequest
2 голосов
/ 03 апреля 2012

У меня есть следующий код:

        public void OpenFile(string FileName)
        {
            if (FileName == null)
                throw new ArgumentNullException("FileName", "OpenFile: Filename is null");


            List<int> readItems = new List<int>();
            using (StreamReader reader = new StreamReader(FileName))
            {
                string line;
                int batchItem;
                while ((line = reader.ReadLine()) != null)
                {
                    if (int.TryParse(line, out batchItem))
                    {
                        readItems.Add(batchItem);
                    }
                }
            }

            CurrrentFile = FileName;
            FileInfo f = new FileInfo(FileName);
            lock (LockObject)
            {
                TextWriter = f.AppendText();
                TextWriter.AutoFlush = true;
            }

            if (readItems.Count > 0)
                FileOpened(readItems);


        }

Я пытаюсь обнаружить возможные проблемы, например, / Имя файла равно нулю.

В классе, который ловит и регистрирует исключения, у меня, очевидно, есть catch(ArgumentNullException ex)

Должен ли я также отлавливать возможные исключения, генерируемые конструктором StreamReader и конструктором FileInfo?

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

Ответы [ 4 ]

4 голосов
/ 03 апреля 2012

В целом, если вы следуете нескольким простым правилам, вы можете существенно упростить свой код обработки исключений.

1.Только перехватывать и обрабатывать исключения, которые вы на самом деле можете делать что-то о

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

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

try
{
   DoSomeStuff();
}
catch(HolyCrapItBlewedUpException ex)
{
   RecoverFromExplosion();
}
catch(Exception ex)
{
   //I really have no idea what happened, and I can't do
   // anything about it, but I'm going to catch the
   // exception anyway cause it makes me feel better
}

Есть кашель исключения из правила выше, но это подводит нас к нашему второму правилу.

2.Используйте только обобщенную обработку исключений для ведения журнала и скрытие реализации

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

try
{
   DoSomeStuff();
}
catch(Exception ex)
{
   //At this point it's a bug... we need to squash it!
   LogException(ex);
   ShowUserRecoveryOptions();
}

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

public void MakeMeASandwich()
{
   try
   {
      MakeCallerASandwich();
   }
   catch(SecurityException ex)
   {
      //It's still best to distinguish between certain exceptions
      // as long as it makes sense to the caller.
      throw new NoIWillNotMakeYouASandwichException(ex);
   }
   catch(Exception ex)
   {
      throw new SorryICantMakeYouASandwichException(ex);
   }
}

3.Избегайте исключений, таких как Чума!

Исключения должны быть, ну ... исключительными!В большинстве случаев вы должны избегать исключений, просто программируя их заранее.Настоящее исключение должно представлять то, что вы не можете предсказать, произойдет ли это.Простой пример - проверка на наличие файла.

try
{
   File.Open("blah.txt");
}
catch(FileNotFoundException ex)
{
   File.Create("blah.txt");
}

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

var fileName = "blah.txt";

if(!File.Exists(fileName))
   File.Create(fileName);

File.Open(fileName);

Теперь все еще возможно выбросить FileNotFoundException здесь, но как мы справимся с этим?Очевидно, что этот код больше не может ничего с этим поделать, поскольку произошло что-то действительно ИСКЛЮЧИТЕЛЬНОЕ .Мы можем позволить исключению всплыть на следующий уровень, поскольку здесь нет ничего значимого.

1 голос
/ 03 апреля 2012

Всегда убедитесь, что ваше общее исключение, а именно предложение SystemException / ApplicationException / Exception catch должно быть последним. Так что готовьтесь к очевидному. В вашем случае исключение SecurityException, FileNotFound, PathNotFound и т. Д. Пожалуйста, проверьте документ MSDN для этих API и какие исключения они выдают.

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

1 голос
/ 03 апреля 2012

Должен ли я ловить возможные исключения, выдаваемые Конструктор StreamReader и конструктор FileInfo?

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

0 голосов
/ 03 апреля 2012

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

...