2011-01-28 2 views
12

Если я поставлю пустые блоки блокировки для своего кода на C#, это будет эквивалент для инструкции VB.NET «On Error Resume Next».Что такое лучшая альтернатива «On Error Resume Next» для C#?

try 
{ 
    C# code; 
} 

catch(exception) 
{ 
} 

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

+14

Отсутствие альтернативы 'On Error Resume Следующий »был не просто непреднамеренным наблюдением ... Почему ты * возможно, нуждаешься в этом? Если вы объясните мотивацию своих размышлений об этом, я уверен, что кто-то здесь может дать вам лучшее решение. –

+0

@Cody Grey - обновлена ​​причина запроса. Спасибо – Neel

+0

@Michael Shimmins - спасибо – Neel

ответ

18

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

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

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

+5

+1 для входа в систему для защиты следующего разработчика. –

5

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

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

5

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

Некоторые примеры того, почему использовать On Error Resume Next в Basic 6.0 код Визуальный:

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

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

+0

Использование только 'On Error Resume Next' в таких случаях не хуже. Существует причина, по которой «On Error Resume Next» существует, но это должно использоваться с другими операторами - '' '' '' '' '' '' '' '' '' '' '' 'только один тип ошибки и' On Error GoTo 0', чтобы возобновить сбор ошибок, а не просто пропустить торговый центр. – Mike

+7

@Mike: Я не совсем уверен, что вы пытаетесь сказать здесь. Ответ Джо явно разъясняет, что вы «обрабатываете ошибку, возникающую, если ключ не существует». Я использую (d) 'On Error Resume Next' почти исключительно в VB 6 для реализации моих собственных процедур обработки ошибок. Я думаю, мы все говорим то же самое. Заявление имеет свое место в VB 6, если вы используете его с умом, но в VB.NET его нет вообще (поскольку он вводит синтаксис превосходного 'try' /' catch'). –

+0

@ Коди Серый - согласился. Я работал над большой командой продуктов около 10 лет назад, и стандартная политика заключалась в том, чтобы включить On Error Resume Next во все наши VB-коды. ОДНАКО вы подверглись бы серьезной критике в обзоре кода, если бы ваш код не постоянно тестировал условия ошибки, как выполнялась процедура. Это привело к некоторому чрезвычайно подробному коду, но можно было написать твердый код, который обрабатывал исключительные случаи. –

4

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

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

+1

Я предполагаю, что вы могли бы обернуть каждое заявление, которое может сломаться в его собственном try/empty catch, чтобы получить аналогичный эффект, но это будет какой-то злой код. –

+0

@ Тим: Хех, так долго, что мне не нужно поддерживать этот код! –

1

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

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

1

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

3

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

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

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

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

1

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

2

«При повторном повторном включении» позволяет использовать «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 - это плохая привычка и кодовая подборка. Это форум 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, но иногда нет; Я получаю раздражающую ошибку, что таблица не содержит этого поля. Я мог бы заботиться о меньшем, если это не так, потому что это не требуемые данные. В этом случае 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. C# - мой выбор языков, но это не так много RAD-язык как VB по многим причинам. Я надеюсь, что все программисты поймут, что несколько основных языков (т. Е. C) просто запускаются и не останавливают выполнение на необработанных ошибках; это задача разработчиков, чтобы проверить их, где они считают нужным. On Error Resume Next - это самое близкое к этой парадигме в мире 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/поймать блок, функция лямбда проверки существования каждой таблицы, строки , комбинацию столбцов, которая извлекается из набора данных, который динамически заполнялся xml. Это можно проверить по строкам, но для этого потребуется много избыточного кода (здесь у нас одинаковое количество исполняемого кода, но гораздо меньше написанного кода для поддержки). К сожалению, это может считаться еще одной плохой практикой «One Line Functions». Я нарушаю это правило в случае лямбда и анонимных функций.

Поскольку .NET предлагает так много способов проверить состояние объектов; On Error Resume Next не так важен для экспертов VB, как это было до .NET, но все же приятно иметь вокруг; особенно когда вы кодируете что-то, что будет пустой тратой времени, чтобы не закодировать быстро и грязно. Для вас Java конвертируется в C#; присоединиться к миру Microsoft и перестать притворяться, что если это говорят 10000 промежуточных программистов на Java и C#, это должно быть правдой, потому что, если один из главных гуру Microsoft Guru (например, любой из тех, кто создал язык VB и .NET), явно противоречит вам их развитие.NET, это неверно, и вы выглядите глупо. Я хочу всю функциональность, которую я могу получить на C# и VB и F #, и на любой другой язык, который мне нужно использовать. C# является элегантным, но VB более развит из-за того, что он намного длиннее, но они оба делают «Same Thing» и используют одни и те же объекты. Изучите их как хорошо, так и, пожалуйста, прокомментируйте либо в сравнении разговоров; это тошнотворно для тех из нас, кто был с середины девяностых, используя технологии Microsoft на высоком уровне.

1

Как было сказано в @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);} 
      ); 
0

Я старую шляпу на 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 { PerformAction(); } catch (Exception _e) { } 

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

удачи ...

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