Почему в этом случае сопоставление с образцом завершается неудачно? - PullRequest
2 голосов
/ 25 ноября 2011

У меня есть простая иерархия исключений:

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)

и эти три (фиктивные) функции:

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:

  • firstFunction вызывает исключение FirstLevelException
  • secondFunction перехватывает его, помещает в исключение SecondLevelException и выбрасывает
  • thirdFunction перехватывает его, помещает его в исключение ThirdLevelException и выбрасывает
  • вызывающий абонент может поймать исключение ThirdLevelException.

Все хорошо.Теперь я изменяю ThirdFunction следующим образом:

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

все становится странным: похоже, что сопоставление с шаблоном в ThirdFunction больше не работает, а SecondLevelException распространяется вплоть до вызывающей функции ThirdFunction, безбыть заключенным в ThirdLevelException.

Я уверен, что есть логическое объяснение, которое мой C # -деформированный разум не может видеть.Может кто-нибудь, пожалуйста, пролить немного света?

1 Ответ

7 голосов
/ 25 ноября 2011

Поведение, которое вы описали, является правильным - когда вы пишете 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)))

Никто не будет писать такой код на практике, но я надеюсь, что это демонстрирует проблему!

Кстати: я полагаю, это связано с вашей ранееТАК вопрос об обработке исключений в конвейере.Я добавил ответ , который может помочь вам понять проблему.(Проблема в том, что операции переноса конвейера в try .. with не предотвратят исключения, которые происходят внутри конвейерных функций).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...