Можно ли отлаживать элемент инициализации структуры / класса по члену? - PullRequest
5 голосов
/ 27 мая 2020

Инициализация класса следующим образом:

var x = new Item()
{
 ID = (int)...,
 Name = (string)...,
 ..
};

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

Есть ли способ отлаживать каждое присвоение по отдельности? Я видел, как отладчик по отдельности останавливается 3 раза на таких выражениях, как foreach(x in y), поэтому кажется немного странным, что он не делает этого здесь и отвлекает от использования этого удобного синтаксиса инициализации. Может быть, я могу использовать более подробный шаг отладки?

Ответы [ 3 ]

5 голосов
/ 08 июня 2020

Ваш вопрос: «Можно ли отладить элемент инициализации структуры / класса по члену?».

Итак, заранее я не отвечаю на этот вопрос в том виде, в каком он сформулирован. потому что, когда я внимательно читаю текст вашего сообщения, кажется, что основной вопрос заключается в том, как определить «линию курения» root причину этого InvalidCastException прямо тогда, когда это происходит.

То, что я нашел в похожих Ситуация заключается в том, что если Visual Studio можно заставить прервать работу в момент возникновения InvalidCastException, т.е. в указанной c строке , тогда стек вызовов и локальные переменные будут гораздо более непосредственными и полезными.

К сожалению, прерывание при выбросе подавляется настройками Visual Studio по умолчанию для многих типов исключений. Но очень легко включить "прерывание при выбросе" для ВСЕХ исключений. Просто измените этот параметр по умолчанию в окне исключений в Visual Studio с этого:

Default Exception Settings

на это:

enter image description here

Это не «всегда» помогает, но это хорошее начало. Это так просто, почему бы не попробовать сначала, чтобы увидеть, возможно ли быстрое разрешение. Надеюсь, это окажется полезным в вашем случае.

2 голосов
/ 08 июня 2020

Не уверен, что это вариант в VS 2017, у меня под рукой только 2019. В ваших настройках в разделе Параметры -> Отладка -> Общие снимите флажок Переступать через свойства и операторы . Затем установите точку останова в вашем инициализаторе и пройдите через нее с помощью F11 (Step-Into). Вы будете нажимать на каждый установщик свойств, пока не будет сгенерировано исключение.

0 голосов
/ 08 июня 2020

Пожалуйста, извините, если я чего-то упускаю (удаляю, если это так), но использую недопустимое приведение, например:

struct Item
{
    public int ID { get; set; }
    public Derived Derived { get; set; }
}
public class Base
{
    public string Name { get; set; }
}
public class Derived : Base
{
    public string AdditionalProperty { get; set; }
}
var baseClass = new Base()
{
    Name = "foo",
};
try
{
    var x = new Item()
    {
          ID = (int)20,
          Derived = (Derived)baseClass,
    };
}
catch(Exception e)
{
          Console.WriteLine(e.Message);
}

аккуратно отлавливает такую ​​ошибку Unable to cast object of type 'Base' to type 'Derived'. в vs2017

Однако это прерывается при первой ошибке, мы могли бы захотеть инициализировать объект таким образом и зарегистрировать все ошибки приведения без выхода из инициализации. Мы можем сделать это, реализовав собственное приведение для этого примера:

public static T TryCast<T>(Object _object)
        {
            try
            {
                return (T)_object;
            }
            catch (Exception e)
            {
                Console.WriteLine($"Cant cast object of type {_object.GetType().ToString()} to object of type {typeof(T)}");
            }
            return default(T);
        }
 public static T TryCast<T>(IConvertible _object)
        {
            try
            {
                return (T)Convert.ChangeType(_object, typeof(T));
            }
            catch (Exception e)
            {
                Console.WriteLine($"Cant convert object of type {_object.ToString()} to object of type {typeof(T)}");
            }
            return default(T);
        }

Новые типы для демонстрационных целей

struct Item
    {
        public int ID { get; set; }
        public double FooDouble { get; set; }
        public Base Base { get; set; }
        public Derived Derived { get; set; }
        public string Bar { get; set; }
    }
    public class Base
    {
        public string Name { get; set; }
    }
    public class Derived : Base
    {
        public string AdditionalProperty { get; set; }
    }

Затем мы можем инициализировать наш объект следующим образом:

var derived = new Derived()
            {
                Name = "DerivedFoo",
                AdditionalProperty = "Bar"
            };
            var _base = new Base()
            {
                Name = "BaseFoo"
            };
            var x = new Item()
            {
                ID = Utils.TryCast<int>("please no"),
                FooDouble = Utils.TryCast<double>(2),
                Base = Utils.TryCast<Base>(derived),
                Derived = Utils.TryCast<Derived>(_base),
                Bar = "Foo"
            };

И мы аккуратно регистрируем любые ошибки, которые могут возникнуть при кастинге:

Result in the console

...