我有这个简单的异常层次结构:
type FirstLevelException(msg) = inherit System.Exception (msg)
type SecondLevelException(msg, inner) = inherit System.Exception (msg, inner)
type ThirdLevelException(msg, inner) = inherit System.Exception (msg, inner)
Run Code Online (Sandbox Code Playgroud)
和这三个(虚拟)功能:
member this.FirstFunction a =
raise (new FirstLevelException("one"))
member this.SecondFunction a =
try
this.FirstFunction a
with
| :? FirstLevelException as ex -> raise (new SecondLevelException("two", ex))
member this.ThirdFunction a =
try
this.SecondFunction 25
with
| :? SecondLevelException as ex -> raise (new ThirdLevelException("three", ex))
Run Code Online (Sandbox Code Playgroud)
当你调用ThirdFunction时很容易看到:
都好.现在我按以下方式更改thirdFunction:
member this.ThirdFunction a =
25 |>
try
this.SecondFunction
with
| :? SecondLevelException as ex -> raise (new ThirdLevelException("three", ex))
Run Code Online (Sandbox Code Playgroud)
事情变得很奇怪:看起来ThirdFunction中的模式匹配不再起作用,并且SecondLevelException一直传播到ThirdFunction调用者,而不包含在ThirdLevelException中.
我确信有一个合乎逻辑的解释是我的C#变形的头脑看不到.有人可以解释一下吗?
您描述的行为是正确的 - 当您编写时25 |> expr,将对代码进行expr求值,然后使用25参数调用结果(函数).
在您的情况下,结果expr是一个函数,表达式的评估(返回函数)受到try块的保护.但是,一旦返回该函数,它就会转义该try块,并且在异常处理程序之外进行调用.
要在此返回的函数中移动异常处理,您必须编写如下内容:
25 |> (fun n ->
try
// You need to call the function (i.e. give it something as an argument)
// inside the try-with block, otherwise it won't be executed here!
this.SecondFunction n
with
| :? SecondLevelException as ex -> raise (new ThirdLevelException("three", ex)))
Run Code Online (Sandbox Code Playgroud)
在实践中没有人会写这种代码,但我希望它能证明这个问题!
顺便说一句:我想这与您之前关于处理管道中的异常的SO问题有关.我在那里添加了答案,这可以帮助您理解问题.(问题是管道的包装操作try .. with不会阻止在流水线函数内发生的异常).
| 归档时间: |
|
| 查看次数: |
378 次 |
| 最近记录: |