F#异常没有被正确抓住

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)

问题是excatch块捕获ConfigFileVersionIncompatabilityException异常,它应该被第一个块捕获.

我尝试使用:? System.Exception as ex而不是只是ex它仍然表现相同.

我错过了什么吗?

[在初始帖子后1分钟编辑,删除不相关的代码.]

Tom*_*cek 6

在反序列化期间发生异常时,该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)