pau*_*aul 0 f# exception-handling exception
我有一个F#异常,它没有被正确的catch块捕获.
这是相关的代码:
exception ConfigFileVersionIncompatabilityException of string
[<XmlType("config")>]
type Configuration() = class
let thisVersion : string = "1.0"
let mutable fileVersion : string = thisVersion
[<XmlAttribute("version")>]
member x.FileVersion
with get() = fileVersion
and set v = if v <> thisVersion
then raise (ConfigFileVersionIncompatabilityException(String.Format("Was expecting version {0} but read version {1}.", thisVersion, v)))
end
module FilterFileFunctions =
let sampleConfigFilename = "sample.filters"
let readConfig (file : string) =
try
use xmlDoc = new StreamReader(file) in
let s = XmlSerializer(typeof<Configuration>)
s.Deserialize(xmlDoc) :?> Configuration |> Success
with
| ConfigFileVersionIncompatabilityException(s) ->
String.Format("Failed to read the configuration file: \"{0}\";\nThe following reason was given:\n{1}", file, s)
|> Failure
| ex ->
String.Format("Failed to read the configuration file: \"{0}\";\n{1}", file, ex)
|> Failure
Run Code Online (Sandbox Code Playgroud)
问题是ex
catch块捕获ConfigFileVersionIncompatabilityException
异常,它应该被第一个块捕获.
我尝试使用:? System.Exception as ex
而不是只是ex
它仍然表现相同.
我错过了什么吗?
[在初始帖子后1分钟编辑,删除不相关的代码.]
在反序列化期间发生异常时,该Deserialize
方法将捕获它并将其包装在内部InvalidOperationException
.这意味着您需要进行聊天InvalidOperationException
,然后分析InnerException
属性以获取用户定义的异常.
try // ..
with
| :? InvalidOperationException as invOp ->
match inv.InnerException with
| :? ConfigFileVersionIncompatabilityException as e ->
printfn "%s" e.Data0
| _ -> // generic handler
| e -> // generic handler
Run Code Online (Sandbox Code Playgroud)
该Data0
属性公开了异常所携带的值(我使用它,因为在使用时无法在模式匹配中轻松访问它:?
).但是,您可以match
使用活动模式避免表达式的丑陋嵌套(以及通用处理程序的重复):
let (|InnerException|) (e:exn) =
e.InnerException
try // ..
with
| InnerException(ConfigFileVersionIncompatabilityException s) ->
printfn "%s" s
| _ -> // generic handler
Run Code Online (Sandbox Code Playgroud)