Visual Studio 2017 не позволяет отладчику останавливаться при исключении в Activator.CreateInstance

У меня есть код, который пытается создать объект сначала с помощью одного конструктора, а затем, если это не удается, с конструктором по умолчанию:

MyClass Construct(MyField f1, MyField f2) 
{
    try 
    {
        return (MyClass)Activator.CreateInstance(typeof(MyClass), f1, f2);
    }
    catch 
    {
        var o = (MyClass)Activator.CreateInstance(typeof(MyClass)); 
        o.f1= f1; 
        o.f2=f2;
        return o;
    }
}

Я хочу, чтобы отладчик не останавливался при обнаружении исключения. Я пробовал [DebuggerStepThrough], [DebuggerHidden] и [DebuggerNonUserCode] безуспешно.

Я также пробовал запустить: "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\VsRegEdit.exe" set "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community" HKLM Debugger\Engine AlwaysEnableExceptionCallbacksOutsideMyCode dword 1 как рекомендовано здесь, но не повезло.

Есть ли способ сделать это в VS2017? В качестве альтернативы, есть ли способ использовать Activator.CreateInstance, который вернет null вместо генерации исключения?

(с использованием Visual Studio 2017 15.8.0 превью 4.0)


person kofifus    schedule 22.08.2018    source источник
comment
Во-первых, есть настройки для отслеживания типов исключений, и вы можете просто отключить их, однако тот факт, что вы используете исключения для управления потоком вашего приложения, является реальной проблемой здесь, хотя это может работать, это плохой дизайн ... . Вы действительно должны контролировать это, вы знаете свои типы, или, если нет, вы можете использовать отражение, чтобы понять это, в любом случае это немного воняет   -  person TheGeneral    schedule 23.08.2018
comment
ах, понял, мне нужно поискать конструктор, использующий Type.GetConstructor! если вы хотите оставить ответ, я отмечу это, спасибо!   -  person kofifus    schedule 23.08.2018
comment
Я думаю, что реальный вопрос здесь: почему вы используете Activator.CreateInstance для типа, который знаете во время компиляции? Почему бы просто не использовать new MyClass(f1, f2)?   -  person MickyD    schedule 23.08.2018
comment
Кроме того, чтобы предотвратить остановку отладчика при возникновении исключения, если оно обнаружено - см. stackoverflow.com/a / 34172404/585968   -  person MickyD    schedule 23.08.2018


Ответы (1)


Быстрый и неприятный подход - найти конструкторы GetConstructors и посмотреть на GetParameters счетчик, а затем выполнить соответствующее ветвление.

var ctors = typeof(A).GetConstructors();
// assuming class A has only one constructor
var ctor = ctors[0];
foreach (var param in ctor.GetParameters())
{
    Console.WriteLine(string.Format(
        "Param {0} is named {1} and is of type {2}",
        param.Position, param.Name, param.ParameterType));
}

И снова, вероятно, есть более эффективные способы сделать это. Однако, по крайней мере, вы не используете исключения для управления потоком вашего приложения.

Если вы знаете тип своих классов, вы также можете сравнивать типы. Или, если вы используете базовые классы или интерфейс, вы можете использовать дженерики с ограничениями. Во многом это зависит от того, чего мы не видим и почему

person TheGeneral    schedule 22.08.2018