为什么在调试并将其作为Exception捕获时会看到派生Exception的(空)属性?

时间:2015-08-10 13:49:54

标签: c#

在Stackoverflow上阅读和this问答时,我想知道为什么你可以看到List<string>但无法访问它。

根据我的理解,您无法访问基类中派生类的成员。那么,为什么会这样呢? 显然你可以看到它,但你不能用它做点什么。

2 个答案:

答案 0 :(得分:1)

你显然无法做到这一点

catch (Exception ex)
{
    var adresses = ex.lpAdresses;
}

因为ex的编译时类型是Exception,而不是CustomException

调试器OTOH可以检查ex引用的对象的运行时类型并显示其属性。类似于:

catch (Exception ex)
{
    var cex = ex as CustomException;
    if (cex != null)
    {
        var adresses = cex.lpAdresses;
    }
}

答案 1 :(得分:1)

调试器有关于存储在变量中的实际运行时类型的信息 - 这是.NET中运行时元数据的一部分。

这意味着它实际上可以显示完全您正在查看的内容,而编译器可以使用的唯一内容是 compile -time类型 - in换句话说,您明确指定的那个(例如Exception)或隐式(var)指定。

您可以使用反射API复制相同的行为。例如,如果您知道您尝试阅读的类型包含名为Name的属性,其类型为string,但您不知道将要传递的实际类型,你可以使用这样的东西:

public static string GetName(object someObject)
{
  return (string)someObject.GetType().GetProperty("Name").GetValue(someObject);
}

但是,当然,既然我们已经拥有C#4,我们也可以使用dynamic来更轻松,更快地实现同样的目标(虽然不是更安全 - 它仍然是运行时绑定):

public static string GetName(dynamic someObject)
{
  return someObject.Name;
}

显然,dynamic没有IntelliSense :)另外值得注意的是,反射允许您读取和操作对象的所有内部状态,而dynamic仍然遵循通常的可访问性修饰符。