2017-02-22 28 views
3

При отладке кода C# Visual Studio показывает исходное местоположение необработанного исключения.Неправильное расположение необработанного исключения при отладке кода F # в Visual Studio

Например, при отладке следующего кода Visual Studio показывает необработанное DivideByZeroException было брошено на линии 9.

Я хочу сделать то же самое в F #. Ниже приведен мой перевод выше кода на F #.

open System 

let f() = raise (new DivideByZeroException()) // line 3 

[<EntryPoint>] 
let main argv = 
    try 
     f() 
    with :? ArgumentException ->() // line 9 
    0 

Когда я отладить этот код на Visual Studio, он разбивает на необработанное исключение и точек линии 9. Я ожидаю, что он указывает линию 3.

Я попытался Microsoft.FSharp.Core.Operators.reraise, но это не изменил результат.

EDIT захват # отладки экрана

C

Debugging screen, C#

F захват # отладки экрана

Debugging screen, F#

Сформирован IL для C#

ILSpy for C#

Сформирован IL для F #

ILSpy for F#

+3

Держу пари, что компилятор ввел функцию на сайт вызова. Вы строите с включенными оптимизациями? Можете ли вы просмотреть скомпилированный код с помощью ILSpy? –

+0

Оптимизация не включена. Я проверил его с помощью ILSpy. Похоже, что это не указано, он называет команду «ретрой». Но не уверен, потому что его трудно читать. –

+0

Интересно, что IL для кода C# не использует команду rethrow, потому что она только улавливает ArgumentException. Сгенерированный IL для F # захватывает System.Object и проверяет его сгенерированным кодом, и когда он не соответствует ему, вызывает команду rethrow. Таким образом, в IL-коде была разница. –

ответ

3

Проблема заключается в том, когда вы добавили попробовать/с утверждением в вашем вызове f(), выброшенное исключение распространяющейся в той точке кода который находится в «основном» блоке.

Для того, чтобы обрабатывать исключения в функции F(), как в вашем C, например #, переместить попытку/с к е(), например:

let f() = 
try 
    raise (System.DivideByZeroException()) // exception is handled here 
    with | InnerError(str) -> printfn "Error1 %s" str 

[<EntryPoint>] 
let main argv = 
    f() 
    0 
+0

Да, лучше обработать исключение как можно раньше. Но когда я получаю необработанное исключение из-за ошибки неожиданно, я должен найти ошибку. В моем примере я ожидал ArgumentException, поэтому вызов Func() находится в try {} block. Но не ожидал DivideByZeroException, вызванный ошибкой. Проблема для примера выше. Отладчик Visual Studio помогает, когда я использую C#, но не использую F #.Извините, если мой вопрос неясен. –

+2

@Nozo Проблема в том, что F # не выполняет обработку исключений так же, как C# (как вы обнаружили). Одна вещь, которую вы можете сделать за счет некоторого беспорядка кода, заключается в том, чтобы использовать #if DEBUG для выполнения обработки excpetion одним способом, когда вы отлаживаетесь, а другим способом - в режиме деблокирования. –

+0

Спасибо за совет. Это будет эффективным решением. В моем примере я отключу try-catch для ArgumentException при отладке. –

0

Я видел ту же самую проблему и filed an issue. Обходным путем является добавление --generate-filter-blocks в «Другие флаги» на странице «Построить» свойств проекта.