为什么Visual Studio Debugger不会枚举BitArray并向我显示结果?

时间:2011-04-04 20:24:15

标签: c# visual-studio debugging visual-studio-debugging

对于以下C#代码行:

BitArray bitty = new BitArray(new[] {false, false, true, false});

如果我在Watch窗口中评估“bitty”,我看不到该集合的成员。如果我评估“bitty,results”,它应该枚举IEnumerable并显示结果,我会收到消息“只有可枚举的类型可以有结果视图”,即使BitArray是IEnumerable。

为什么调试器会这样做?

CLARIFICAITON:我在问VS Debugger Expression Evaluator中发生了什么,而不是询问如何在调试器中查看BitArray。

1 个答案:

答案 0 :(得分:15)

结果视图仅适用于符合以下条件的集合:

  1. 实施IEnumerable<T>IEnumerable(VB.Net仅适用于IEnumerable<T>
  2. 实施IListIList<T>ICollectionICollection<T>(仅限C#限制)
  3. 具有DebuggerTypeProxy属性
  4. 在debugee进程中加载​​了System.Core.dll
  5. 在这种情况下,BitArray同时实现IEnumerableICollection。后者取消了它与结果视图一起使用的资格。

    解决此问题的一种方法是使用Cast扩展方法。这将生成IEnumerable<T>值,您可以使用结果视图

    bitty.Cast<bool>(), results
    

    #2的原因是多种因素的组合:

    • 结果视图最初是为解决一个非常具体的问题而发明的:C#迭代器(以及扩展LINQ查询)的调试体验很差。没有好的方法来查看IEnumerable<T>的内容。
    • “结果”视图不是免费,并且确实存在非常具体的风险。特别是它将热切地和同步地将整个集合加载到存储器中。这可能会导致数据库查询,极大或无限集合支持的集合出现问题
    • 每个已知的IList/<T>ICollection<T>类型都有一个让您查看内容的方法

    因此,C#团队决定将风险降至最低,而不是将IEnumerable<T>添加到他们认为已经很好地显示的类型中。 VB.Net选择了另一个方向,并将为任何IEnumerable<T>显示它。

    你可能会理所当然地问两个团队如何看待相同的数据并做出不同的决定。它归结为视角,当然还有时间。 VB.Net团队非常热衷于提供出色的LINQ调试体验。 VB.Net在提供丰富的调试+ ENC经验方面有着悠久的历史,因此更习惯/愿意承担此类风险,并且还具有测试它的带宽。 C#只是更加厌恶风险,非常严格的时间表,并务实地决定反对它。

    注意:我之前对IEnumerable不被支持的困惑是因为VB表达式求值程序实际上就是这种情况。 C#表达式求值程序确实支持IEnumerable,但遵循上述规则。