是否可以逐个调试一个struct/class初始化成员?

Is it possible to debug a struct/class initialization member by member?

像这样初始化 class:

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

我在其中一项作业中收到 InvalidCastException。它们有很多,即使我逐行 运行 调试器,整个表达式也会出现异常。该异常没有提供任何线索,无论它试图将什么投射到什么。

有没有办法单独调试每个作业?我已经看到调试器在像 foreach(x in y) 这样的表达式上分别停止了 3 次,所以它在这里没有这样做似乎有点奇怪,并且有损于使用这种方便的初始化语法的吸引力。也许我可以使用更细粒度的调试步骤?

如果我遗漏了什么(如果是这样的话会删除)但使用无效的演员表,请原谅:

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"
            };

我们会整齐地记录转换时可能发生的任何错误:

不确定这是否是 VS 2017 中的一个选项,我手头只有 2019。在 选项 -> 调试 -> 常规下的设置中,取消选中 跨过属性和运算符。然后在您的初始化程序中设置一个断点并使用 F11 (Step-Into) 单步执行它。您将命中每个 属性 setter 直到抛出异常。

您的问题是"Is it possible to debug a struct/class initialization member by member?"。

所以,首先,我没有直接回答那个问题的措辞,因为当我仔细阅读你post的正文时,它听起来像是基本问题是如何在 InvalidCastException 发生时立即识别 'smoking line' 根本原因。

我在类似情况下发现的是,如果 Visual Studio 可以在 InvalidCastException 发生的那一刻中断,即 在该特定行 然后调用堆栈和局部变量更加直接和有用。

不幸的是,'break when thrown' 被许多异常类型的 Visual Studio 默认设置所抑制。但是为所有异常打开 'break when thrown' 非常容易。只需在 Visual Studio 中的例外 window 中更改此默认设置:

对此:

这没有 "always" 帮助,但这是一个好的开始。这很容易,为什么不先尝试一下,看看是否可以快速解决问题。希望这对你的情况有用。