Почему вызовы вызванных методов не обрабатывают все исключения как необработанные исключения в .Net 4.0+?

Я заметил, что функция отладки «Только мой код»/«Брейк при необработанных исключениях» не работает при динамическом вызове метода с использованием .net Framework 4.0 или выше. Если я изменю проект, чтобы использовать фреймворк 3.5, он будет работать нормально.

Учитывая этот пример приложения командной строки:

using System;

namespace InvokeFail
{
    class Program
    {
        static void Main(string[] args)
        {
            HandledExceptions();
        }
        public static void HandledExceptions()
        {
            try
            {
                Fail();
            }
            catch (NotImplementedException)
            {
                // handle it amazingly well
            }

            try
            {
                InvokeFail();
            }
            catch (NotImplementedException)
            {
                // handle it amazingly well
            }
        }

        private static void Fail()
        {
            throw new NotImplementedException();
        }

        private static void InvokeFail()
        {
            try
            {
                typeof(Program).GetMethod("Fail", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)
                                      .Invoke(null, null);
            }
            catch (System.Reflection.TargetInvocationException ex)
            {
                throw ex.InnerException;
            }
        }
    }
}

И эти параметры отладки VS:

Диалоговое окно отладки параметров VS

Окно исключений отладчика VS

Вот изображение, где останавливается отладчик, и его стек вызовов: Debugger No Debuggy


person Daryl    schedule 27.05.2014    source источник
comment
Предположение об ошибке в модуле запуска модульных тестов всегда должно быть последним в вашем списке. Вы ожидали, что исключение будет вызвано методом Fail(). Это не так, у вас есть ошибка в коде Reflection, которая вызывает исключение NullReferenceException. Вам нужен BindingFlags.NonPublic для закрытых методов.   -  person Hans Passant    schedule 27.05.2014
comment
@HansPassant, спасибо, что поймали это. Когда я создавал пример ошибки, я нашел эту ошибку и исправил ее, и подумал, что обновил вопрос SO. Однако вопрос остается в силе. Запуск этого тестового образца по-прежнему имеет разрыв отладчика в методе Fail при рефлексивном вызове...   -  person Daryl    schedule 27.05.2014
comment
Хм, отлично работает на моей машине. Что-то еще забыли обновить?   -  person Hans Passant    schedule 27.05.2014
comment
@HansPassant Я преобразовал его в консольное приложение и обновил вопрос, та же проблема. Интересно, имеет ли это отношение к VS 2013?   -  person Daryl    schedule 27.05.2014
comment
@HansPassant Я наконец понял, что это проблема .net 4.0+. Платформа 3.5 ведет себя так, как ожидалось.   -  person Daryl    schedule 27.05.2014
comment
Хм, очень сомнительно. Я тестировал на 4.5.1 так же, как и вы.   -  person Hans Passant    schedule 28.05.2014
comment
@Daryl - Я предполагаю, что вы на самом деле смотрите на это задом наперед. Я думаю, что на самом деле это была ошибка в 3.5, которая позволила ему работать, и они исправили ее в 4.0, или, может быть, это не ошибка, а просто изменение поведения, которое вызывает Reflected. Мне кажется, что ваш код на самом деле необработан, потому что вызывающая сторона перевела исключение.   -  person Erik Funkenbusch    schedule 28.05.2014
comment
@ErikFunkenbusch Можете ли вы преобразовать свой комментарий в ответ и сослаться на это: заголовок stackoverflow.com/questions/4117228/? Я отмечу это как ответ.   -  person Daryl    schedule 28.05.2014
comment
@ Дэрил - Давай, ответь на свой вопрос, я не считаю свой комментарий достаточно авторитетным, чтобы быть ответом.   -  person Erik Funkenbusch    schedule 28.05.2014


Ответы (1)


По-видимому, в .net framework было внесено целенаправленное изменение в версии 4.0.

См. здесь определение ошибки и возможные обходные пути. < /а>

Это был просто комментарий к этому вопросу, но он имеет смысл:

Когда в свойстве возникает исключение, оно не обрабатывается там, в свойстве. Вызывающий метод MethodInfo (который вызывается из PropertyInfo.GetProperty()) переводит реальное выброшенное исключение в TargetInvocationException. Таким образом, вы обрабатываете не реальное исключение, вы обрабатываете обернутое исключение.

person Daryl    schedule 28.05.2014