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

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

Если я поставлю пустые блоки catch для моего кода на С#, это будет эквивалент для оператора VB.NET "При повторном возобновлении следующего".

try
{
    C# code;
}

catch(exception)
{
}

Причина, по которой я спрашиваю об этом, заключается в том, что мне нужно преобразовать код VB.NET в С#, а старый код имеет ~ 200 "On Error Resume Next", хотя я использую правильный try {} catch {} в своем новом коде, но есть ли лучшая альтернатива?

4b9b3361

Ответ 1

Я обнаружил, что программисты VB часто засоряют код многими операторами On Error Resume Next из (плохой) привычки. Мое предложение состояло в том, чтобы начать с не подавленных исключений и посмотреть, что на самом деле ломается. Возможно, не так много проблем, как вы думаете. И наоборот, чем больше регрессионных тестов вы можете сделать, тем лучше; могут быть некоторые случаи ребер, которые работают только при игнорировании ошибок.

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

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

Ответ 2

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

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

Ответ 3

Вам нужно проанализировать операторы On Error Resume Next один за другим и посмотреть, какова их цель. Некоторые могут быть просто неаккуратным кодом, но есть веские причины для On Error Resume Next в коде Visual Basic 6.0.

Некоторые примеры использования On Error Resume Next в коде Visual Basic 6.0:

  • Чтобы проверить, существует ли данный ключ в коллекции Visual Basic 6.0. Единственный способ сделать это - получить доступ к элементу по ключу и обработать возникшую ошибку, если ключ не существует. При преобразовании в .NET вы можете заменить это на проверку наличия ключа.

  • Разбор строки на целое число. В .NET вы можете использовать TryParse.

Ответ 4

Нет, это не то же самое.

При использовании On Error Resume Next, VB перейдет к следующей строке, если возникнет ошибка. При попытке /catch выполнение переходит к блоку catch, если возникает ошибка (исключение).

Ответ 5

Хотя On Error Resume Next, безусловно, злоупотребляют больше, чем он используется законно, есть места, где это было бы полезно даже в VB.NET.

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

"Правильный" способ сделать это с помощью VB.NET - это определить, какие свойства принтера поддерживаются каждой версией Excel, прочитать используемую версию и назначать только свойства, реализованные в этой версии. Для этого потребуется много исследований и некоторый код, все для небольшой выгоды. On Error Resume Next было бы более практичным решением.

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

Ответ 6

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

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

Проблема с "On Error Resume Next" в VB.NET заключается в том, что он загружает объект err в каждую строку исполняемого кода и, следовательно, медленнее, чем Try/catch. Меня несколько настораживает, что этот форум проверял и продвигал безуспешный ответ, который утверждал, что использование On Error Resume Next - это плохая привычка и кодовая подборка. Это форум С#; должен ли он действительно использоваться для программистов на С#, чтобы делать снимки на другом языке, на котором они не очень хорошо разбираются?

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

        'Pull Xml from file And dynamically create a dataset.
        Dim strXML As String = File.ReadAllText("SomeFilePath.xml")
        Dim srXmL As StringReader = New StringReader(strXML)
        Dim dsXML As DataSet = New DataSet()
        dsXML.ReadXml(srXmL)

        'Any error above will kill processing. I can ignore the first two errors and only need to worry about dataset loading the XML.
        If Err.Number <> 0 Then
            MsgBox(Err.Number & Space(1) & Err.Description)
            Exit Sub 'Or Function
        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()

В приведенном выше коде необходимо было только обрабатывать одно возможное условие ошибки; хотя было две ошибки до того, как был обработан третий. Требования к разработке 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, но все же приятно иметь вокруг; особенно когда вы кодируете что-то, что будет пустой тратой времени, чтобы не закодировать быстро и грязно. Для вас Java конвертируется в С#; присоединиться к миру Microsoft и перестать притворяться, что если это говорят 10000 промежуточных программистов на Java и С#, это должно быть правдой, потому что, если один из главных гуру Microsoft Guru (например, любой из тех, кто создал язык VB и .NET), явно противоречит вам их развитие самой .NET, это неверно, и вы выглядите глупо. Я хочу всю функциональность, которую я могу получить на С# и VB и F #, и на любой другой язык, который мне нужно использовать. С# является элегантным, но VB более развит из-за его гораздо более длительного срока пребывания, но они оба делают "ту же вещь" и используют одни и те же объекты. Изучите их как хорошо, так и, пожалуйста, прокомментируйте либо в сравнении разговоров; это тошнотворно для тех из нас, кто был с середины девяностых, используя технологии Microsoft на высоком уровне.

Ответ 7

Использование "On Error Resume Next" не является хорошей идеей для обработки ошибок (конечно, это мое личное мнение, но, похоже, большинство разработчиков согласны со мной). Поскольку другие ребята советуют вам в предыдущих сообщениях, используйте Try...Catch...FinallyVB.NET или С#).

Это очень умный вариант для обработки ошибок, но он также позволит вам ничего не делать с ошибкой (пустой блок catch):) Я бы предложил вам поместить каждую строку кода (что может вызвать ошибку) в разделить Try...Catch Block, чтобы у вас была возможность делать все, что угодно, если возникает ошибка. Happy Coding guys:)

Ответ 8

Правильная замена .NET для "on error resume next" - это использование методов Try___. В Visual Basic 6.0, чтобы выяснить, существовал ли ключ в коллекции, нужно было либо вручную искать коллекцию (ужасно медленно), либо попытаться проиндексировать ее и уловить любую ошибку, которая произошла, если ее там не было. В VB.NET объект Dictionary (который является улучшенной версией старой коллекции) поддерживает метод TryGetValue, который укажет, была ли попытка получить значение успешным, не вызывая ошибки, если это не так. Ряд других объектов .NET поддерживают аналогичную функциональность. Существует несколько методов, которые должны иметь "попробовать" эквиваленты, но не использовать (например, Control.BeginInvoke), но их достаточно, чтобы их обертывание отдельно в Try/Catch не было слишком обременительным.

Ответ 9

Мне кажется, что те люди, которые изобрели "On Error Resume Next", имели в виду что-то, когда они его создали. Ответ на ваш вопрос не будет, в С# ничего не эквивалентно этой конструкции. У нас есть на С# и .Net множество функций, которые так жаждут заботы и внимания, что через некоторое время становится утомительным, чтобы удовлетворить всех "исключительным поведением". Когда почти все может сделать исключение, само слово теряет смысл. Вы внутри итерации, и что вы должны делать, если несколько тысяч миллионов предметов оказались исключительными? Резюме Далее может быть одним из удобных ответов.

Ответ 10

Как было сказано в @Tim Medora, вы должны приложить все усилия, чтобы избежать использования такого подхода при кодировании. Однако в некоторых случаях это полезно, и можно эмулировать такое поведение. Вот функция и пример ее использования. (Обратите внимание, что некоторые элементы кода были написаны с использованием С# 6)

    /// <summary>
    /// Execute each of the specified action, and if the action is failed, go and executes the next action.
    /// </summary>
    /// <param name="actions">The actions.</param>
    public static void OnErrorResumeNext(params Action[] actions)
    {
        OnErrorResumeNext(actions: actions, returnExceptions: false);
    }

    /// <summary>
    /// Execute each of the specified action, and if the action is failed go and executes the next action.
    /// </summary>
    /// <param name="returnExceptions">if set to <c>true</c> return list of exceptions that were thrown by the actions that were executed.</param>
    /// <param name="putNullWhenNoExceptionIsThrown">if set to <c>true</c> and <paramref name="returnExceptions"/> is also <c>true</c>, put <c>null</c> value in the returned list of exceptions for each action that did not threw an exception.</param>
    /// <param name="actions">The actions.</param>
    /// <returns>List of exceptions that were thrown when executing the actions.</returns>
    /// <remarks>
    /// If you set <paramref name="returnExceptions"/> to <c>true</c>, it is possible to get exception thrown when trying to add exception to the list. 
    /// Note that this exception is not handled!
    /// </remarks>
    public static Exception[] OnErrorResumeNext(bool returnExceptions = false, bool putNullWhenNoExceptionIsThrown = false, params Action[] actions)
    {
        var exceptions = returnExceptions ? new Collections.GenericArrayList<Exception>() : null;
        foreach (var action in actions)
        {
            Exception exp = null;
            try { action.Invoke(); }
            catch (Exception ex) { if(returnExceptions) { exp = ex; } }

            if (exp != null || putNullWhenNoExceptionIsThrown) { exceptions.Add(exp); }
        }
        return exceptions?.ToArray();
    } 

Пример, а не:

        var a = 19;
        var b = 0;
        var d = 0;
        try { a = a / b; } catch { }
        try { d = a + 5 / b; } catch { }
        try { d = (a + 5) / (b + 1); } catch { }

вы можете:

            var a = 19;
            var b = 0;
            var d = 0;
            OnErrorResumeNext(
                () =>{a = a / b;},
                () =>{d = a + 5 / b;},
                () =>{d = (a + 5) / (b + 1);}
            );

Ответ 11

Я старая шляпа на VB6. Сначала небольшой урок...

Есть причины использовать On Error Resume Next. В основном для удобства чтения. В VB6 у вас есть два способа реализовать захват ошибок. Вы можете использовать "inline" On Error Resume Next следующим образом.

On Error Resume Next
<something that may throw an error>
If Err.Number <> 0 Then
   <do something about this specific line of code>
   Err.Clear()
End If

Или вы можете увидеть это:

Sub DoSomething

   On Error Goto Handler1
   <do something that causes an error>

   On Error Goto Handler2
   <do something that may cause an error>

   Exit Sub

   Handler1:
   <log error or something>
   Resume Next

   Handler2:
   <log error or something>
   Resume Next

End Sub  

Но в старом коде VB6 вы, скорее всего, тоже увидите это...

Sub PerformThis
On Error Resume Next

End Sub

Независимо от того, что это просто конвертировать эти случаи в Try Catch... Если вам нужно потопить ошибку, используйте быстрый "встроенный" просмотр "Включение ошибки". Далее выполните это.

try { _objectinfo.Add(_object.attribute1); } catch (Exception _e) { }

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

try { PerformAction(); } catch (Exception _e) { }

Сделайте это в случае, когда подпрограмма PerformAction() содержит заголовок On Error Resume Next в верхней части кода, используйте Try Catch в вызывающей подпрограмме

Удачи...