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

Я пропустил Visual Basic "Включение ошибки в следующем" на С#. Как мне теперь передавать ошибки?

В Visual Basic я написал только On Error Resume Next в начале моей программы, и ошибки были подавлены во всем проекте.

Здесь, в С#, я очень скучаю по этой функции. Обычная обработка try-catch для каждой отдельной процедуры не только очень трудоемкая, но и приводит к нежелательным эффектам. Если ошибка встречается, даже если она обрабатывается, код не продолжается с точки, в которой он произошел. С On Error Resume Next код продолжался с точки ошибки, пропуская только вызов функции, вызвавший ошибку.

Я пока еще не занимаюсь С#, но, возможно, в С# существует более эффективная обработка ошибок, чем примитив try-catch.

Я также хотел бы иметь имя модуля или функции, где произошла ошибка, а также номер строки в моем сообщении об ошибке. Класс Exception не предоставляет этих функций, насколько мне известно. Любые идеи (управляемые, конечно, без привлечения классов процессов в моем собственном приложении)?

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

Мое решение, которое я нашел, чтобы решить несколько из моих проблем:

public partial class Form1 : Form
{

    public Form1()
    {
        InitializeComponent();
    }

    [STAThread]
    static void Main()
    {
      Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); //setup global error handler
      Application.Run(new Form1());
    }

    private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
    {   
            MessageBox.Show("Unhandled exception: " + e.Exception.ToString()); //get all error information with line and procedure call
            Environment.Exit(e.Exception.GetHashCode()); //return the error number to the system and exit the application
    }

    private void button1_Click(object sender, EventArgs e)
    {
        string s = ""; s.Substring(1, 5); //Produce an error
    }

   }
4b9b3361

Ответ 1

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

Не удается создать новый баланс аккаунта? Это хорошо, пусть просто сохранит его как 0. Никто никогда не узнает, верно?

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

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

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

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

Как-то С# всегда вызывает много ошибок при выполнении, этот язык типичен.

Нет, это просто говорит о том, что вы делаете это неправильно.

Ответ 2

Нет.

Говоря как программист ex-VB, позвольте мне заверить вас: это самая худшая и наиболее злоупотребляемая функция, когда-либо добавленная на любой язык. Здесь вместо этого:

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

Как уже отмечал Джон, на самом деле довольно редко требуется обработка исключений по всему месту. Обычно вы просто позволяете исключению пузыря до более высокого вызывающего абонента, потому что произошло что-то плохое. И когда у меня есть try, это чаще всего try/finally (не try/catch) - с using и lock (и т.д.) Являются особыми случаями для удобство.

Ответ 3

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

Ответ 4

Нет, вы не можете. Это невозможно в С# (и не должно быть на каком-либо другом языке).

Истинное использование для этого в VB заключалось в том, чтобы обрабатывать ошибки в некоторой части кода, точно так же, как try / catch. Вы включаете его, проверяете с помощью Err.Number <> 0, выполняете свою работу и восстанавливаете поток ошибок с помощью On Error GoTo 0 или перенаправляете на метку, которая следует за другим путем для обработки ошибки или продолжения выполнения On Error GoTo someErrorCase:.

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

Поверь мне. Я был программистом VB, и это было очень интересно, когда я перестал читать лучшие практики.

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

Кроме того, исключения С# очень полезны и имеют всю необходимую информацию. Если у вас нет проблемы с самим исключением, просто откройте его и посмотрите в его внутреннем исключении (я всегда вижу внешние исключения при разработке для Интернета, поскольку весь код находится на более высоком уровне).

Ответ 5

Вы использовали эту функцию VB неправильно, и вам так повезло, что вы не можете использовать ее как на С#.

При использовании функции в VB вы должны проверять состояние ошибки после каждой операции, которая может привести к ошибке. При правильном использовании он не меньше кода, чем try...catch блокирует каждую операцию, которая может привести к ошибке.

Итак, если вы считаете, что вам нужно делать больше ошибок в С#, вы делали слишком мало обработки ошибок раньше.

Ответ 6

"При повторном повторном совпадении" допускает "Inline Error Handling", которая является обработкой ошибок уровня эксперта в VB. Концепция состоит в том, чтобы обрабатывать ошибки по очереди, либо выполняя действие на основе ошибки, либо игнорируя ошибку, когда она полезна, но работает в последовательности, в которой она написана, и не использует переходы кода.

К сожалению, многие новички использовали "On Error Resume Next", чтобы скрыть либо их недостаток, либо ленивость от тех, кто использует свои приложения, игнорируя все ошибки. Try/catch - это обработка ошибок уровня блока, которая в мире pre -.NET была промежуточной по дизайну и реализации.

Проблема с "On Error Resume Next" в VB.NET заключается в том, что он загружает объект err в каждую строку исполняемого кода и, следовательно, медленнее, чем try/catch.

https://msdn.microsoft.com/en-us/library/aa242093(v=vs.60).aspx

Говорят, что промежуточные программисты на С#, не имеющие реального опыта работы с VB, не должны пытаться удержать С# и ограничить функцию из-за их странного презрения к другому языку "Microsoft Net". Рассмотрим следующий код:

//-Pull xml from file and dynamically create a dataset.
 string strXML = File.ReadAllText(@"SomeFilePath.xml");
 StringReader sr = new StringReader(strXML);
 DataSet dsXML = new DataSet();
 dsXML.ReadXml(sr);

string str1 = dsXML.Tables["Table1"].Rows[0]["Field1"].ToString();
string str2 = dsXML.Tables["Table2"].Rows[0]["Field2"].ToStrin();
string str3 = dsXML.Tables["Table3"].Rows[0]["Field3"].ToStrin();
string str4 = dsXML.Tables["Table4"].Rows[0]["Field4"].ToString();
string str5 = dsXML.Tables["Table5"].Rows[0]["Field5"].ToString();

Если xml обычно имеет значение для Field3, но иногда нет; Я получаю раздражающую ошибку, что таблица не содержит этого поля. Я мог бы заботиться о меньшем, если это не так, потому что это не требовало данных. В этом случае ON Error Resume Next позволит мне просто игнорировать ошибку, и мне не нужно будет кодировать каждую строку кода, устанавливая переменные, проверяющие наличие комбинации таблиц, строк и столбцов с методами Содержит. Это небольшой пример; Я мог бы вытащить тысячи комбинаций таблиц, столбцов, строк из больших файлов. Также предположим, что строковые переменные должны быть заполнены таким образом. Это необработанный код, и будут проблемы.

Рассмотрим версию VB.NET и ON Error Resume Next:

 On Error Resume Next

        Dim strXML As String = File.ReadAllText("SomeNonExistentFileCausingAnErrorCondition.xml")
        If String.IsNullOrEmpty(strXML) Then
            strXML = strSomeOtherValidXmlThatIUseWhenTheFileIsEmpty
        End If
        Dim srXmL As StringReader = New StringReader(strXML)
        Dim dsXML As DataSet = New DataSet()
        dsXML.ReadXml(srXmL)
        If Err.Number <> 0 Then
            MsgBox(Err.Number & Space(1) & Err.Description)
            Exit Sub
        End If

        Dim str1 As String = dsXML.Tables("Table1").Rows(1)("Field1").ToString()
        Dim str2 As String = dsXML.Tables("Table2").Rows(2)("Field2").ToString()
        Dim str3 As String = dsXML.Tables("Table3").Rows(3)("Field3").ToString()
        Dim str4 As String = dsXML.Tables("Table4").Rows(4)("Field4").ToString()

В приведенном выше коде необходимо было только обрабатывать одно возможное условие ошибки; даже если произошла ошибка при загрузке файла. В появившемся окне "Ошибка об ошибке" на самом деле разрешили мне возобновить работу по назначению, что позволило мне проверить условие строки и использовать мою альтернативную строку (я хорошо знаю, что я мог бы проверить наличие файла и избежать ошибки файла, но если это был хороший файл, в котором ничего нет, strXML будет пустой строкой). Ошибка, которая была критической для остальной части кода, была обработана, и метод был удален из-за того, что загруженный набор данных был первостепенным для остальной части обработки за его пределами (обработка, которую можно было запустить, игнорируя при этом любые ошибки). Ошибка файла может быть проигнорирована, поскольку я проигнорировал его, или я мог бы проверить условие ошибки и зарегистрировать его.

Требования к разработке RAD. С# - мой выбор языков, но это не так много RAD-язык как VB по многим причинам. Я надеюсь, что все программисты поймут, что несколько основных языков (т.е. C) просто запускаются и не останавливают выполнение на необработанных ошибках; это задача разработчиков, чтобы проверить их, где они считают нужным. On Error Resume Next - это самое близкое к этой парадигме в мире Microsoft.

К счастью,.NET дает множество дополнительных возможностей для обработки этих ситуаций; Я ускользнул от Содержит. Итак, в С# вам нужно повысить уровень знаний на вашем языке, и вы, в соответствии со спецификацией языка С#, работаете над такими проблемами. Рассмотрим решение для обработки большого блока повторяющихся строк кода, который может содержать ошибку раздражающего выброса:

try
            {
                if (!File.Exists(@"SomeFilePath.xml")) { throw new Exception("XML File Was Not Found!"); }
                string strXML = File.ReadAllText(@"SomeFilePath.xml");
                StringReader sr = new StringReader(strXML);
                DataSet dsXML = new DataSet();
                dsXML.ReadXml(sr);

                Func<string, string, int, string> GetFieldValue = (t, f, x) => (dsXML.Tables[t].Columns.Contains(f) && dsXML.Tables[t].Rows.Count >= x + 1) ? dsXML.Tables[t].Rows[x][f].ToString() : "";

                //-Load data from dynamically created dataset into strings.
                string str1 = GetFieldValue("Table1", "Field1", 0);
                string str2 = GetFieldValue("Table2", "Field2", 0);
                string str3 = GetFieldValue("Table3", "Field3", 0);
                //-And so on.

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            } 

Хотя в блоке try/catch функция лямбда проверяет наличие каждой комбинации таблиц, строк, столбцов, которые извлекаются из набора данных, который динамически заполнялся xml. Это можно проверить по строкам, но для этого потребуется много избыточного кода (здесь у нас одинаковое количество исполняемого кода, но гораздо меньше написанного кода для поддержки). К сожалению, это может считаться еще одной плохой практикой "One Line Functions". Я нарушаю это правило в случае лямбда и анонимных функций.

Так как .NET предлагает так много способов проверить состояние объектов; On Error Resume Next не так важен для экспертов VB, как это было до .NET, но все же приятно иметь вокруг; особенно когда вы кодируете что-то, что будет пустой тратой времени, чтобы не закодировать быстро и грязно. Никто, кто когда-либо использовал VB на экспертном уровне, никогда не заявлял, что On Error Resume Next (встроенная обработка ошибок) - самая худшая функция, когда-либо добавленная к языку. Тем не менее, это было широко использовано для новичков.