Show/Hide Toolbars

XSharp

用途

TRY、CATCH FINALLY 用于声明异常处理块。

语法

TRY
 guardedStatements
[CATCH [[variableName] AS exceptionType] [WHEN whenexpression]
 exceptionHandlingStatements
]  
[FINALLY
 cleanupStatements
]
END TRY

 

参数

 

variableName接收异常的变量名。变量名是可选项。如果只指定类型,异常仍会被捕获,但不会存储在本地变量中。

 

exceptionTypeCATCH 代码块将捕获的异常类型。

 

whenexpression逻辑表达式,用于确定特定 CATCH 块是否应处于活动状态

 

exceptionHandlingStatements处理异常情况的零个或多个语句。

 

cleanupStatements零个或多个语句,在退出 TRY 块之前执行必要的清理。

备注

TRY-CATCH-FINALLY 块用于捕获和处理代码块中可能抛出的异常。异常可能由 CLR、Vulcan.NET 运行时库、第三方库或使用 THROW 语句的应用程序代码产生。

TRY 块

TRY 代码块中的语句有时被称为 "保护 "语句。这些语句可能会导致异常,而您希望处理这些异常。

CATCH 块

一个异常处理块可以包含任意数量的 CATCH 块(包括零)。每个声明了变量名和类型的 CATCH 块都将接收该类型的异常。接收异常的 CATCH 块会隐式声明一个包含捕获异常的局部变量。这个隐式声明的局部变量只在 CATCH 代码块的范围内有效。该变量的名称不得与任何显式声明的 LOCAL 或参数相同,否则会出现编译时错误。不过,在多个 CATCH 代码块中使用相同的变量名是合法的。由于每个 CATCH 代码块的变量只在其外层代码块中可见,因此不会发生冲突。

 

CATCH 代码块也可以不声明变量名,但声明异常类型。在这种情况下,异常仍会被捕获,但不会存储在局部变量中。

 

CATCH 代码块也可以不声明任何变量名和异常类型。这种类型的 CATCH 代码块将捕获任何异常,相当于声明了一个异常类型为 System.Exception 的 CATCH 代码块。

 

如果声明了多个 CATCH 代码块,它们出现的顺序很重要。CLR 将按顺序检查 CATCH 子句,并调用与抛出的异常相匹配的第一个子句。这不仅包括指定的特定异常类,还包括任何派生类。因此,应先捕获较特殊的异常类型,再捕获不那么特殊的异常类型。

 

CATCH 块中声明的异常类型必须始终是 System.Exception 或由其派生的类。

 

如果没有为已抛出的异常声明合适的 CATCH 块,控制权将被传递到下一个最高级别的异常处理块。如果没有更高级的异常处理块,或者没有可以处理该异常的异常处理块,应用程序将终止。

 

可以使用 THROW 关键字明确地将异常传递给下一个最高级别的异常处理块。

Finally 块

如果声明了 FINALLY 代码块,无论 TRY 代码块如何退出,其中的任何语句都会被执行。这就为执行任何清理(如释放资源)提供了一种机制。即使没有合适的 CATCH 代码块来处理异常,finally 代码块中的代码也会被执行。

兼容性说明:

TRY-CATCH-FINALLY 块与 BEGIN SEQUENCE-RECOVER 块类似,但比 BEGIN SEQUENCE-RECOVER 块更灵活。不过,为了向后兼容,仍支持 BEGIN SEQUENCE 和 RECOVER。

 

请注意,使用 BREAK 抛出的异常不会被 TRY-CATCH-FINALLY 块捕获,因为 BREAK 抛出的数据封装在 USUAL 中,而 USUAL 并不继承于 System.Exception。

 

然而,使用 THROW 抛出的异常将被下一个最高的 BEGIN SEQUENCE 代码块(如果有)捕获,如果已声明 RECOVER USING 变量,异常将被封装在 USUAL 中。

 

还要注意的是,CanBreak() 运行时函数不会检测当前执行是否在 TRY 代码块中。提供 CanBreak() 函数只是为了与现有的 Visual Objects 代码和 BEGIN SEQUENCE 块兼容,而不应依赖它来确定执行是否在异常处理块中。由于 CLR 中不存在该功能,因此无法确定执行是否在异常处理块中,而且执行可能是在以 Vulcan.NET 以外的语言编译的代码中进行的。

示例

下面的示例测试除数为零的除法,并捕获 CLR 在除数为零时抛出的异常。任何其他异常都会传播到下一个最高的异常处理块(如果有的话)。如果没有异常处理块,应用程序将以未处理的除以零异常结束。

FUNCTION DivisionTest( x AS INT, y AS INT ) AS INT
  TRY
    RETURN x / y
  CATCH e AS System.DivideByZeroException
     ? "除以零!", e
    RETURN 0
  END TRY

下面的示例演示了多个 CATCH 块和一个 FINALLY 块:

USING System.IO
 
FUNCTION ReadFile( filename AS STRING ) AS STRING
  LOCAL s AS STRING
 
  TRY
     s := File.ReadAllText( filename )
  CATCH e AS DirectoryNotFoundException
     ? "未找到目录", e
  CATCH e AS IOException
     ? "发生 IO 异常", e
  CATCH e AS UnauthorizedAccessException
     ? "拒绝访问", e
  CATCH
     ? "其他例外情况"
  FINALLY
     ? "全部完成!"
  END TRY
 
  RETURN s                            

参见

BEGIN SEQUENCE
THROW