2013-09-28 3 views
1

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

Скажем, у меня есть этот код:

string fileName = Path.Combine(Application.StartupPath, "sometextfile.txt"); 

// There's a possibility that the file doesn't exist <<<<<<<<<<<<<<<<<<<<< 
if (!File.Exists(fileName)) 
{ 
    // Do something here 
    return; 
} 

// Therefore, this will return an exception 
using (StreamReader file = 
    new StreamReader(fileName)) 
{ 
    // Some code here 
} 

Естественно, что я хотел бы сделать, это сообщить пользователю с MessageBox говоря: «Файл не найден». Есть ли эффективный или лучший способ сделать это?

Другая идея, что у меня есть, чтобы создать перечисление который содержит ожидаемые коды ошибок, то создать метод, который будет вызывать MessageBox выдавалось сообщение об ошибке для этой конкретной ситуации:

enum ErrorCodes {null, zero, ...} 
public void showError(ErrorCodes error) 
{ 
    string message; 
    switch (error) 
     { 
     case ErrorCode.null: 
     { 
      message = "value cannot be null"; 
      break; 
     } 
     case ErrorCode.zero: 
     { 
      message = "cannot divide by zero"; 
      break; 
     } 
} 

MessageBox.Show(message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); 
} 
+4

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

+1

Да, я понимаю, но я хочу показать пользовательское сообщение, которое пользователи могут легко понять, и не лучше ли избежать исключения, чем поймать его? – CudoX

+0

Вы должны отделить презентацию сообщения от доступа io. Возможно, ваш код когда-нибудь будет использоваться в консольном приложении? Btw, используйте исключения только для неожиданных путей выполнения, а не для чего-то вроде несуществующих файлов. –

ответ

1

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

Если я правильно понимаю ваш вопрос вы хотите знать, нужно ли это сделать:

public void button_Click() { 
    if(!File.Exists(textBox.Text)) { 
     MessageBox.Show("Could not find the file"); 
     return; 
    } 

    ProcessFile(textBox.Text); // would have thrown an exception if the file didn't exist 
} 

Это было бы хорошо, за исключением случаев, ProcessFile бросает любой другой вид исключений не будет обрабатываться.

Вы можете сделать это:

public void button_Click() { 
    try { 
     ProcessFile(textBox.Text); // throwns an exception if the file didn't exist 
    } catch(Exception ex) { 
     MessageBox.Show(GetUserMessage(ex)); 
     return; 
    } 
} 

На мой взгляд, лучше сделать так:

public void button_Click() { 
    try { 
     if(!File.Exists(textBox.Text)) { 
      MessageBox.Show("Could not find the file"); 
      return; 
     } 

     ProcessFile(textBox.Text); // throwns an exception if the file didn't exist 
    } catch(Exception ex) { 
     MessageBox.Show(GetUserMessage(ex)); 
     return; 
    } 
} 

Таким образом, вы можете обеспечить наиболее конкретное сообщение пользователю соответствующий тому, что он делает с этой точки зрения. Например, если он пытался открыть файл Excel, вы могли бы сказать: «Не удалось найти файл Excel, который вы хотите импортировать».

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

В качестве альтернативы вы могли бы сделать что-то подобное с этим:

public void button_Click() { 
    try { 
     if(!File.Exists(textBox.Text)) { 
      throw new UserException("Could not find the file"); 
     } 

     ProcessFile(textBox.Text); // throwns an exception if the file didn't exist 
    } catch(Exception ex) { 
     MessageBox.Show(GetUserMessage(ex)); 
     return; 
    } 
} 

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

Исключение в классах

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

Например, вы не должны хотеть этого:

class MyFileHandler { 
    public void OpenFile(string fileName) { 
     if(!File.Exists(fileName)) return; 
     // do stuff 
    } 

    public void DoStuff() { 
     // do stuff 
    } 
} 

Теперь, если разработчик называется myFileHandlerInstance.OpenFile("note.txt") он предположил, что это сработало.Вы можете вернуть логическое значение, так как:

class MyFileHandler { 
    public bool OpenFile(string fileName) { 
     if(!File.Exists(fileName)) return false; 
     // do stuff 
     return true; 
    } 

    public void DoStuff() { 
     // do stuff 
    } 
} 

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

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

public string GetUserErrorMessage(Exception ex) { 
    if(ex is FileLoadException) { 
     var fileLoadException = (FileLoadException)ex; 
     return "Sorry but we failed to load the file: " + fileLoadException.FileName; 
    } 
} 

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

+0

Спасибо за предложение, я просто хочу уточнить - что, если я уже проверил подробности об исключении?По-прежнему целесообразно обернуть его вокруг оператора try-catch и уловить его данные о исключениях, а не перейти к «user-MessageBox» (поскольку уже ожидается, что уже обнаружен разработчик_____0_03) – CudoX

+0

@ Gelo103097 Я не конечно, я понимаю ваш вопрос, но я обновил свой ответ, пытаясь ответить на него. –

1

Эти вещи никогда не бывает легкими. По определению исключение (например, испанская инквизиция) никогда не ожидалось. В первом примере файл может существовать при вызове File.Exist, но тогда не существует, когда вы пытаетесь его открыть (файл удален, сеть не удалась, вытащил палец и т. Д.). Что касается лучшей практики: защитите себя, где можете, поймите только те исключения, которые вы знаете, как обращаться и надеяться на лучшее. Программы потерпят неудачу, и самое лучшее, что вы можете сделать, это убедиться, что необработанные сбои передаются как можно яснее пользователю кода (в основе вашего второго примера).

Обнаружение отказа сильно зависит от того, что делает код и кто его использует. MessageBox часто используются, но обычно не «полезны», потому что, если причина ошибки не понятна пользователю, единственное, что они могут сделать, это отправить вам jpg-изображение (это лучший пример: -D). Предоставление способа журнала проблем и/или настраиваемый диалог, который позволяет пользователям вырезать/вставлять информацию (например, трассировку стека), гораздо полезнее. Подумайте о том, когда пользователь выбирает файл, и есть сетевая икота. Они сообщают вам, что они получили эту ошибку о том, что файл не найден, но когда вы или они выглядят, он существует, потому что к тому времени сеть работает правильно. Простое сообщение «файл не найден» дает вам достаточно информации, поэтому вы должны сказать пользователю «Я не знаю, рад, что он работает сейчас» ... это не внушает доверия. Лучшая практика заключается в том, чтобы оставить себе достаточно «сухарей», чтобы хотя бы иметь общее представление о том, что произошло. Даже что-то вроде полного пути к файлу может дать вам подсказки, необходимые для выяснения того, что пошло не так.

Смежные вопросы