"On Error Resume Next" 允许在 VB 中进行 "内联错误处理",这是专家级别的错误处理。其概念是逐行处理错误,根据错误执行操作或在有益时忽略错误 - 但按照编写代码的顺序运行代码,而不使用代码跳转。
不幸的是,许多新手使用 "On Error Resume Next" 来隐藏他们的能力不足或因懒惰而忽略所有错误,从而欺骗使用他们应用程序的人。Try/catch 是块级错误处理,在 .NET 之前的世界中是中间层次的设计和实现。
在 VB.NET 中使用 "On Error Resume Next" 的问题在于它会在每行执行代码时加载 err 对象,因此比 try/catch 更慢。
https://msdn.microsoft.com/en-us/library/aa242093(v=vs.60).aspx
有人说,没有真正的VB经验的中级C#程序员不应该因为对另一种“Microsoft Net”语言的奇怪鄙视而试图让C#变得愚笨和功能有限。请考虑以下代码:
//-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()
在上面的代码中,只需要处理一个可能的错误条件;即使加载文件时出现错误。On Error Resume Next实际上允许我按照预期恢复,这使我能够检查字符串条件并使用我的备用字符串(我非常清楚也可以检查文件的存在并避免文件错误,但如果它是一个没有任何内容的好文件,则strXML将是一个空字符串)。关键的错误已经处理,并且该方法已退出,因为加载的数据集对其后的处理至关重要(如果需要,可以忽略任何错误运行处理)。文件错误可以被忽略,就像我忽略它一样,或者我可以检查错误条件并记录它。
RAD开发需要On Error Resume Next。C#是我选择的语言,但由于许多原因,它不像VB那样是一种RAD语言。我希望所有程序员都意识到,几种主要语言(例如C)只是运行而不会在未处理的错误上停止执行;开发人员的工作是在他们认为必要的地方进行检查。在Microsoft世界中,On Error Resume Next是最接近该范例的东西。
幸运的是,.NET提供了许多高级选项来处理这些情况;我提到了Contains。因此,在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() : "";
string str1 = GetFieldValue("Table1", "Field1", 0);
string str2 = GetFieldValue("Table2", "Field2", 0);
string str3 = GetFieldValue("Table3", "Field3", 0);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
虽然在try/catch块中,lambda函数正在检查从动态填充的xml数据集中提取的每个表、行、列组合的存在。这可以逐行检查,但需要大量的冗余代码(在这里我们有相同数量的执行代码,但要维护的代码要少得多)。不幸的是,这可能被认为是“一行函数”的另一个不良实践。我在lambda和匿名函数的情况下打破了这个规则。
由于.NET提供了很多检查对象状态的方法;对于VB专家来说,On Error Resume Next并不像在.NET之前那样重要,但仍然很好用;特别是当你编写的东西如果不快速而肮脏地编码就会浪费时间时。任何曾经在专家级别上使用过VB的人都不会声称On Error Resume Next(内联错误处理)是添加到语言中最糟糕的功能。然而,它已经被新手广泛滥用。