如果我为我的C#代码添加空的catch块,它是否等同于VB.NET的“On Error Resume Next”语句。
try
{
C# code;
}
catch(exception)
{
}
我问这个的原因是因为我必须将VB.NET代码转换为C#,旧代码有~200“On Error Resume Next”语句,尽管我在我的中使用了正确的try {} catch {}
新代码,但有更好的选择吗?
答案 0 :(得分:19)
我发现VB程序员常常在(坏)习惯中使用许多On Error Resume Next
语句来填充代码。我的建议是从没有抑制异常开始,看看实际上有什么破坏。可能没有您想象的那么多问题。相反,您可以做的回归测试越多越好;可能有一些边缘情况仅在忽略错误时才起作用。
最终,您需要决定错误处理策略,是否在许多try / catch块中优雅展开,或者让错误渗透到顶级处理程序(两种策略都有其用途)。
如果您最终不得不取消某些例外以符合截止日期,至少会记录这些例外情况,以便下一位处理代码的开发人员不会被空{{{ 1}}。
答案 1 :(得分:6)
虽然有时这是可以接受的,但通常它表示代码味道。如果您100%确定要吞下已发生的异常,您可以按照您的方式执行此操作,但通常如果抛出异常,您应该
通常,您可以通过精心设计的代码获得相同的结果。如果您目前遇到特定错误,请将其添加到您的问题中,但如果您只是出于好奇而不是,那就没有相应的问题,这是一件好事。
答案 2 :(得分:5)
您需要逐个分析On Error Resume Next
语句,看看它们的用途是什么。有些可能只是草率的代码,但在Visual Basic 6.0代码中有On Error Resume Next
的正当理由。
为什么在Visual Basic 6.0代码中使用On Error Resume Next
的一些示例:
检查Visual Basic 6.0集合中是否存在给定密钥。执行此操作的唯一方法是按键访问元素,并处理在密钥不存在时引发的错误。转换为.NET时,您可以通过检查密钥是否存在来替换它。
将字符串解析为整数。在.NET中,您可以使用TryParse。
答案 3 :(得分:5)
不,它不一样。
使用On Error Resume Next时,如果发生错误,VB将跳到下一行。使用try / catch,如果发生错误(异常),执行将跳转到catch块。
答案 4 :(得分:4)
尽管On Error Resume Next
的使用肯定比合法使用的更多,但有些地方甚至在VB.NET中也会有所帮助。
考虑一个为大量Excel属性分配值的程序,例如所有打印机参数的默认值 - Excel中有大量的打印机参数。更高版本的Excel可能具有早期版本不支持的属性,并且要弄清楚每个版本支持哪些属性并非易事。如果属性存在,程序应分配值,但如果使用旧版本的Excel,则忽略该属性。
使用VB.NET执行此操作的“正确”方法是确定每个版本的Excel支持哪些打印机属性,读取正在使用的版本,并仅分配在该版本中实现的属性。这需要大量的研究和一些代码,所有这些都没有什么好处。 On Error Resume Next
将是一个更实际的解决方案。
不幸的是,我现在正面临着这个问题。我要尝试的解决方法是编写一个子程序,只将一个值分配给另一个,忽略错误。我将这个子路由称为每个赋值语句。不太可见,但也不是那么好。
答案 5 :(得分:3)
" On Error Resume Next"允许"内联错误处理",这是VB中的专家级错误处理。这个概念是逐行处理错误,要么根据错误执行操作,要么在有益时忽略错误 - 但是在编写错误的序列中运行代码而不使用代码跳转。
不幸的是,许多新手都使用了#34; On Error Resume Next"通过忽略所有错误来隐藏他们缺乏能力或者使用他们的应用程序的懒惰。 Try/catch
是块级错误处理,在.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
据说,那些没有真正VB经验的中级C#程序员不应该试图让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将允许我忽略错误,并且我不必围绕每行代码进行编码,设置变量检查是否存在与Contains方法的表,行和列组合。这是一个小例子;我可能从大文件中提取数千个表,列,行组合。此外,假设必须以这种方式填充字符串变量。这是未处理的代码,会有麻烦。
考虑一个VB.NET和ON错误恢复下一个实现:
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开发需要On Error Resume Next。 C#是我选择的语言,但由于种种原因,它不像VB语言那么多。我希望所有程序员都意识到几种主要语言(即C)只是运行而不会停止对未处理错误的执行;开发人员的工作是在他们认为必要的地方检查他们。 On Error Resume Next是微软世界中最接近该范例的东西。
幸运的是,.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动态填充的数据集中提取的每个表,行,列组合。这可以逐行检查,但需要大量多余的代码(这里我们有相同数量的执行代码,但编写的代码要少得多)。不幸的是,这可能被认为是“一线功能”的另一种不良做法。&#34;我在lambdas和匿名函数的情况下打破了这个规则。
由于.NET提供了很多方法来检查对象的状态;关于错误恢复接下来对于VB专家来说,它不像.NET之前那样至关重要,但仍然很好用。特别是当你编写一些浪费时间而不编码快速和肮脏的东西时。 Java转换为C#;加入微软的世界,并假装如果10000名中级Java和C#程序员说它,那么它必须是真的,因为如果一个顶级Microsoft Guru(例如创建VB语言和.NET的任何一个)显然与你相矛盾他们开发.NET本身,这是假的,你看起来很愚蠢。我想要用C#和VB和F#以及我需要使用的任何其他语言获得的所有功能。 C#是优雅的,但是由于它的使用期限更长,所以VB更加发展,但它们都做了同样的事情。并使用相同的对象。好好学习它们,或者在比较对话中拒绝评论;对于我们这些自九十年代中期以来一直使用微软技术的人来说,这是令人作呕的。
答案 6 :(得分:2)
使用“On Error Resume Next”不是错误处理的好主意(当然,这是我个人的意见,但似乎大多数开发人员都同意我的看法)。正如其他人在之前的帖子中建议你的那样,使用Try...Catch...Finally
(无论是VB.NET还是C#)。
这是一个非常智能的错误处理选项,但它也允许你对错误(一个空的catch块)不做任何事情:)我建议你把每一行代码(可能导致错误)放入单独Try...Catch Block
,以便在发生错误时您有机会做任何您想做的事情。
快乐的编码家伙:))
答案 7 :(得分:1)
“on next resume next”的正确.NET替换是使用Try___方法。在Visual Basic 6.0中,要查明集合中是否存在密钥,必须手动搜索集合(非常慢),否则尝试对其进行索引并捕获发生的任何错误(如果不存在)。在VB.NET中,Dictionary对象(它是旧Collection的改进版本)支持TryGetValue
方法,该方法将指示尝试获取值是否成功,如果不成功则不会导致错误。许多其他.NET对象支持类似的功能。有一些方法应该具有“尝试”等价物但不具备(例如,Control.BeginInvoke
),但是只有少数方法将它们单独包装在Try/Catch
中并不太繁琐。 / p>
答案 8 :(得分:1)
我碰巧认为那些发明了“On Error Resume Next”的人在创建它时确实有一些想法。 你的问题的答案是否定的,在C#中没有与这个结构相当的东西。 我们在C#和.Net中有很多功能,这些功能非常渴望得到关注和关注,一段时间之后它会让人厌倦,以迎合每个人的“特殊行为”。当几乎所有东西都能抛出异常时,这个词本身就会失去它的含义。 你是在一个迭代中,如果成千上万的项目碰巧是特殊的,你该怎么办?简历下一步可能是一个方便的答案。
答案 9 :(得分:1)
正如@Tim Medora所说,你必须努力避免在编码时使用这种方法。但是,在某些情况下它很有用,并且可以模拟这种行为。这是一个功能和使用它的一个例子。 (请注意,一些代码元素是使用C#6编写的)
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);}
);
你可以:
(?<=^|\s)(?<!\[[+|-])\w*high\w*|\w*high\w*(?![+|-]\])(?=$|\s)
答案 10 :(得分:0)
我是VB6的老帽子。首先是一个简短的教训...
有理由使用On Error Resume Next。主要是为了可读性。在VB6中,您有两种方法来实现错误捕获。您可以使用&#34;内联&#34; 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都是非常直接的......如果您需要接收错误,请使用快速&#34;内联&#34;看错误恢复接下来就这样做..
try { _objectinfo.Add(_object.attribute1); } catch (Exception _e) { }
您还可以通过将代码封装到子例程中来将try catch引发到调用例程......所以如果您需要接收整个子例程,请执行此操作...
try { PerformAction(); } catch (Exception _e) { }
在PerformAction()子例程包含On Error Resume Next的情况下,在代码顶部执行此操作,在调用子例程中使用Try Catch
祝你好运......