在这种情况下,为什么模式匹配因异常而失败? [英] Why does pattern matching fail on an exception in this case?

查看:97
本文介绍了在这种情况下,为什么模式匹配因异常而失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个简单的异常层次结构:

I have this simple exception hierarchy:

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)

和这三个(虚拟)功能:

and these three (dummy) functions:

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))

当您调用ThirdFunction时很容易看到:

It's easy to see that when you call ThirdFunction:

  • firstFunction引发FirstLevelException
  • secondFunction捕获它,将其包装到SecondLevelException中并引发它
  • thirdFunction捕获它,将其包装到ThirdLevelException中并引发它
  • 调用方可以捕获ThirdLevelException.

一切都很好.现在,我通过以下方式更改thirdFunction:

All good. Now I change thirdFunction in the following way:

member this.ThirdFunction a =
    25 |>
    try
        this.SecondFunction
    with
    | :? SecondLevelException as ex -> raise (new ThirdLevelException("three", ex))

事情变得怪异:似乎ThirdFunction中的模式匹配不再起作用,并且SecondLevelException一直传播到ThirdFunction调用者,而没有包装在ThirdLevelException中.

things become weird: it looks like the pattern matching within ThirdFunction does not work anymore, and the SecondLevelException is propagated all the way up to the ThirdFunction caller, without being wrapped in a ThirdLevelException.

我敢肯定,有一个逻辑上的解释是我的C#变形的头脑看不到.有人可以说明一下吗?

I'm sure there is a logical explanation that my C#-deformed mind can't see. Can someone please shed some light?

推荐答案

您描述的行为是正确的-当您编写25 |> expr时,将评估expr中的代码,然后使用调用结果(一个函数) 25作为参数.

The behavior you described is correct - when you write 25 |> expr, the code in expr is evaluated and the result (a function) is then called with 25 as the argument.

在您的情况下,expr的结果是一个函数,并且表达式(返回该函数)的求值受try块的保护.但是,一旦返回该函数,它将转义try块,并在异常处理程序之外进行调用.

In your case, the result of expr is a function and the evaluation of the expression (that returns the function) is protected by your try block. However, once the function is returned, it escapes the try block and the call is made outside of the exception handler.

要在此返回的函数内部移动异常处理 ,您将必须编写如下内容:

To move the exception handling inside this returned function, you would have to write something like this:

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)))

没有人会在实践中编写这种代码,但我希望它能证明问题所在!

Nobody would write this kind of code in practice, but I hope it demonstrates the problem!

顺便说一句:我想这与您先前关于处理管道中的异常的SO问题有关.我在此处添加了答案,这可能有助于您理解问题. (问题在于,在try .. with中包装管道的操作不会阻止在内部管道化函数中发生的异常.)

BTW: I suppose this is related to your earlier SO question about handling exceptions in a pipeline. I added answer there, which may help you understand the problem. (The problem is that wrapping operations of the pipeline in try .. with won't prevent exceptions that happen inside the pipelined functions).

这篇关于在这种情况下,为什么模式匹配因异常而失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆