Какая самая лучшая альтернатива «на ошибке резюме следующим» для C#?

StackOverflow https://stackoverflow.com/questions/4825422

Вопрос

Если я положил пустые блоки для улова для моего кода C#, это будет эквивалентом оператора VB.NET «On Erry Resume Next».

try
{
    C# code;
}

catch(exception)
{
}

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

Это было полезно?

Решение

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

В конечном счете, вам необходимо определить стратегию обработки ошибок, будь то изящное раскручивание внутри многих блоков Try/Catch или позволить ошибкам проходить до обработчика верхнего уровня (обе стратегии имеют свое использование).

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

Другие советы

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

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

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

При использовании по ошибке резюме VB пропустит следующую строку, если произойдет ошибка. С помощью Try/catch выполнение прыгает на блок улова, если возникает ошибка (исключение).

Вам нужно проанализировать 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 вы можете использовать Трипарсе.

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

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

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

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

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

К сожалению, многие новички использовали «на ошибке возобновить следующее», чтобы скрыть либо отсутствие способностей, либо от лени от тех, кто использует свои приложения, игнорируя все ошибки. Try/catch Обработка ошибок на уровне блоков, которая в мире pre-.net была промежуточной по проектированию и реализации.

Проблема с «возобновлением ошибки следующим» в vb.net заключается в том, что он загружает объект ER в каждую строку выполнения кода и, следовательно, медленнее, чем try/catch. Анкет Я несколько встревожился, что этот форум проверил и продвигал бессмысленный ответ, который утверждал, что при повторном резюме ошибки - плохая привычка, а кодовой мусор. Это форум C#; Должны ли он быть использован для программистов C#, чтобы делать снимки на другом языке, на котором они не очень хорошо разбираются?

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

Говорят, что промежуточные программисты C# без реального опыта VB не должны пытаться удержать C# вниз и предназначать ограниченные из -за их странного презрения к другому языку «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, но иногда нет; Я собираюсь получить раздражающую ошибку, что таблица не содержит поле. Мне было бы меньше все равно, если это не так, потому что это не требуется данных. В этом случае при ошибке резюме следующее позволило бы мне просто игнорировать ошибку, и мне не пришлось бы кодировать вокруг каждой строки кода, устанавливающего переменные, проверенные для существования таблицы, комбинации строк и столбцов с содержит методы. Это небольшой пример; Я мог бы вытащить тысячи таблиц, столбцов, комбинаций строк из больших файлов. Также предположим, что строковые переменные должны быть заполнены таким образом. Это беззаботный код, и будут проблемы.

Рассмотрим vb.net и при ошибке резюме следующая реализация:

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 Development потребности при ошибке резюме следующим. C# - это мой выбор языков, но это не такой язык RAD, как VB по многим причинам. Я надеюсь, что все программисты поймут, что несколько основных языков (т.е. c) просто запускаются и не останавливают выполнение по невозможным ошибкам; Работа для разработчиков - проверить их, где они считают необходимым. При ошибке резюме следующим является ближайшая вещь к этой парадигме в мире Microsoft.

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

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 функция Lambda проверяет наличие каждой таблицы, сочетание строки, столбца, которое вытягивается из набора данных, который динамически заполнялся XML. Это может быть проверено строкой по строке, но потребует большого количества избыточного кода (здесь у нас есть одинаковое количество выполняющего кода, но для поддержания гораздо меньшего количества написанного кода). К сожалению, это можно считать еще одной плохой практикой «одной линии функций». Я нарушаю это правило в случае Lambdas и анонимных функций.

Так как .net предлагает так много способов проверить статус объектов; При ошибке резюме следующий не так важен для экспертов VB, как до .NET, но все же приятно иметь вокруг; Особенно, когда вы кодируете что -то, что было бы пустой тратой времени, чтобы не кодировать быстро и грязно. Вам Java обращается в C#; Присоединяйтесь к Microsoft World и перестаньте притворяться, что если 10000 промежуточных программ Java и C# скажут это, то это должно быть правдой, потому что если один из высших уровней Microsoft Guru (например, любой из тех, кто создал язык VB и .NET), очевидно, противоречит вам Их развитие самого .NET, оно ложное, и вы выглядите глупо. Я хочу всю функциональность, которую я могу получить в C# и VB и F# и на любом другом языке, который мне нужно использовать. C# элегантен, но VB более развивается из -за того, что это гораздо более длительное пребывание, но они оба делают «то же самое» и используют одни и те же объекты. Узнайте их обоих или, пожалуйста, устойчиво отменить комментировать либо в сравнении с разговорами; Это тошнотворно для тех из нас, кто существует с середины девяностых, использующих Microsoft Technologies на высоком уровне.

Использование «на ошибке резюме следующим» не является хорошей идеей для обработки ошибок (конечно, это мое личное мнение, но, похоже, что большинство разработчиков согласны со мной). Как посоветовали вам другие парни в предыдущих постах, используйте Try...Catch...Finally (будь то в VB.net или c#).

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

Правильная замена .NET для «на ошибке резюме следующим» - это использование методов try___. В Visual Basic 6.0, чтобы выяснить, существовал ли ключ в коллекции, нужно либо поиск коллекции вручную (ужасно медленной), либо попытаться индексировать ее и поймать любую ошибку, которая произошла, если ее там не было. В VB.net объект словаря (который является улучшенной версией старой коллекции) поддерживает TryGetValue Метод, который будет указывать, является ли попытка получить успешное значение, не вызвав ошибки, если это не так. Ряд других объектов .NET поддерживают аналогичную функциональность. Есть несколько методов, которые должны иметь эквиваленты «попробовать», но не (например, Control.BeginInvoke), но их достаточно мало, которые обертывают их индивидуально в Try/Catch не слишком обременительно.

Я думаю, что те люди, которые изобрели «на ошибке, в следующий раз» имели в виду что -то, когда они создали это. Ответ на ваш вопрос будет нет, нет ничего, что эквивалентно этой конструкции в C#. У нас есть в C# и .NET множество функций, которые настолько жаждут заботы и внимания, что после некоторого некоторого некоторого времени становится утомительным, чтобы удовлетворить «исключительное поведение» каждого. Когда почти все может бросить исключение, само слово теряет, оно немного немного. Вы находитесь в итерации и что вы должны делать, если несколько тысяч миллионов предметов окажутся исключительными? Резюме следующим может быть одним из удобных ответов.

Как сказал @Tim Medora, вы должны приложить усилия, чтобы избежать использования такого подхода при кодировании. Однако в некоторых случаях это полезно, и это возможно подражать такому поведению. Вот функция и пример его использования. (Обратите внимание, что некоторые элементы кода были записаны с использованием C#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);}
            );

Я старая шляпа в VB6. Сначала короткий урок ...

Есть причины для использования на ошибке резюме следующим. В основном для читаемости. В VB6 у вас есть два способа реализации улавливания ошибок. Вы можете использовать «встроенный» на резюме ошибки, а затем.

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 { _objectinfo.Add(_object.attribute1); } catch (Exception _e) { }

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

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

Делайте это в случае, где подпрограмма PerformAction () содержит резюме с ошибкой вверху в верхней части кода, используйте Try Catch в вызовной подпрограмме

Удачи...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top