Подтвердить что ты не робот

С# try-catch-else

Одна вещь, которая прослушивала меня с обработкой исключений с Python на С#, - это то, что в С# не существует способа указать условие else. Например, в Python я мог бы написать что-то вроде этого (примечание, это просто пример. Я не спрашиваю, как лучше всего читать файл):

try
{
    reader = new StreamReader(path);
}
catch (Exception)
{
    // Uh oh something went wrong with opening the file for reading
}
else
{
    string line = reader.ReadLine();
    char character = line[30];
}

Из того, что я видел в большинстве кодов С#, люди просто пишут следующее:

try
{
    reader = new StreamReader(path);
    string line = reader.ReadLine();
    char character = line[30];
}
catch (Exception)
{
    // Uh oh something went wrong, but where?
}

Проблема заключается в том, что я не хочу исключать исключение из диапазона, исходя из того, что первая строка в файле может содержать не более 30 символов. Я хочу только перехватывать исключения, связанные с чтением файлового потока. Есть ли подобная конструкция, которую я могу использовать в С# для достижения того же самого?

4b9b3361

Ответ 1

Поймать определенный класс исключений

try
{
    reader = new StreamReader(path);
    string line = reader.ReadLine();
    char character = line[30];
}
catch (IOException ex)
{
    // Uh oh something went wrong with I/O
}
catch (Exception ex)
{
    // Uh oh something else went wrong
    throw; // unless you're very sure what you're doing here.
}

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

Ответ 2

Вы можете написать это как:

bool success = false;
try {
    reader = new StreamReader(path);
    success = true;
}
catch(Exception) {
    // Uh oh something went wrong with opening the file for reading
}
finally {
    if(success) {
        string line = reader.ReadLine();    
        char character = line[30];
    }
}   

Ответ 3

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

try
{
    reader = new StreamReader(path);
}
catch (Exception)
{
    // Uh oh something went wrong with opening the file for reading
}

string line = reader.ReadLine();
char character = line[30];

Но, конечно, вам нужно будет установить reader в правильное состояние или return из метода.

Ответ 4

Поймать более конкретные исключения.

try {
   reader = new StreamReader(path);
   string line = reader.ReadLine();
   char character = line[30];
}
catch(FileNotFoundException e) {
   // thrown by StreamReader constructor
}
catch(DirectoryNotFoundException e) {
   // thrown by StreamReader constructor
}
catch(IOException e) {
   // some other fatal IO error occured
}

Кроме того, в общем случае обрабатывайте наиболее специфическое исключение и избегайте обработки базы System.Exception.

Ответ 5

Исключения используются по-разному в .NET; они предназначены исключительно для исключительных условий.

На самом деле вы не должны перехватывать исключение, если не знаете, что это значит, и можете на самом деле что-то сделать.

Ответ 6

У вас может быть несколько предложений catch, каждое из которых относится к типу исключения, которое вы хотите поймать. Итак, если вы хотите только поймать IOExceptions, вы можете изменить предложение catch следующим образом:

try
{
    reader = new StreamReader(path);
    string line = reader.ReadLine();
    char character = line[30];
}
catch (IOException)
{    
}

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

try
{
    reader = new StreamReader(path);
    string line = reader.ReadLine();
    char character = line[30];
}
catch (IOException)
{    
}
catch (Exception)
{
}

Ответ 7

Более идиоматично, вы должны использовать оператор using для разделения операции открытия файла из работы, выполненной с содержащимися в ней данными (и включать автоматическую очистку при выходе)

try {
  using (reader = new StreamReader(path))
  {
    DoSomethingWith(reader);
  }
} 
catch(IOException ex)
{
  // Log ex here
}

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

Ответ 8

Вы можете также вставлять свои утверждения try

Ответ 9

Есть ли подобная конструкция, которую я могу использовать в С# добиться того же самого?

Нет.

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

if (line.length > 30) {
   char character = line [30];
} 

Ответ 10

После просмотра других предлагаемых решений, вот мой подход:

try {
    reader = new StreamReader(path);
}
catch(Exception ex) {
    // Uh oh something went wrong with opening the file stream
    MyOpeningFileStreamException newEx = new MyOpeningFileStreamException();
    newEx.InnerException = ex;
    throw(newEx);
}
    string line = reader.ReadLine();
    char character = line[30];

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

Из-за непроверенных исключений вы никогда не сможете быть на 100% уверены, что хватать только IOException из всего блока кода будет достаточно - StreamReader может решить также выбросить какой-либо другой тип исключения, теперь или в будущее.

Ответ 11

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

Конструкция using используется для открытия файла. Если вы выбрали исключение, вам придется не забудьте закрыть файл, даже если вы не поймаете исключение. Это можно сделать с помощью конструкции try { } catch () { } finally { }, но директива using намного лучше для этого. Это гарантирует, что когда область using закончится, переменная, созданная внутри, будет удалена. Для файла это означает, что он будет закрыт.

Изучив документацию для конструктора StreamReader и ReadLine, вы можете увидеть, какие исключения вы можете ожидать. Затем вы можете поймать тех, кого вы найдете. Обратите внимание, что документированный список исключений не всегда завершен.

// May throw FileNotFoundException, DirectoryNotFoundException,
// IOException and more.
try {
  using (StreamReader streamReader = new StreamReader(path)) {
    try {
      String line;
      // May throw IOException.
      while ((line = streamReader.ReadLine()) != null) {
        // May throw IndexOutOfRangeException.
        Char c = line[30];
        Console.WriteLine(c);
      }
    }
    catch (IOException ex) {
      Console.WriteLine("Error reading file: " + ex.Message);
    }
  }
}
catch (FileNotFoundException ex) {
  Console.WriteLine("File does not exists: " + ex.Message);
}
catch (DirectoryNotFoundException ex) {
  Console.WriteLine("Invalid path: " + ex.Message);
}
catch (IOException ex) {
  Console.WriteLine("Error reading file: " + ex.Message);
}

Ответ 12

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

try
{
    reader1 = new StreamReader(path1);
    // if we got this far, path 1 succeded, so try path2
    try
    {
        reader2 = new StreamReader(path2);

    }
    catch (OIException ex)
    {
        // Uh oh something went wrong with opening the file2 for reading
        // Nevertheless, have a look at file1. Its fine!
    }
}
catch (OIException ex)
{
    // Uh oh something went wrong with opening the file1 for reading.
    // So I didn't even try to open file2
}