调试C#中的foreach循环:这是什么迭代?

调试C#中的foreach循环:这是什么迭代?,c#,.net,visual-studio,debugging,foreach,C#,.net,Visual Studio,Debugging,Foreach,除了设置调试变量并在每次启动foreach时递增它之外,在连接了VisualStudio调试器的情况下闯入时,是否有其他方法可以判断这是循环的第X次 我想这可能是VisualStudio的一项功能,而不是添加到编译代码中的功能。可能是您可以使用断点命中计数。不完全是你想要的,但可能会有帮助 在这种情况下,您不想对循环使用还有什么严重的原因。在循环内设置断点,然后右键单击断点以设置条件。您还可以在调试时右键单击以查看命中计数,如果需要,还可以将其重置。您可以将断点命中时计算的布尔表达式设置为有条件

除了设置调试变量并在每次启动foreach时递增它之外,在连接了VisualStudio调试器的情况下闯入时,是否有其他方法可以判断这是循环的第X次


我想这可能是VisualStudio的一项功能,而不是添加到编译代码中的功能。

可能是您可以使用断点命中计数。不完全是你想要的,但可能会有帮助


在这种情况下,您不想对循环使用
还有什么严重的原因。

在循环内设置断点,然后右键单击断点以设置条件。您还可以在调试时右键单击以查看命中计数,如果需要,还可以将其重置。您可以将断点命中时计算的布尔表达式设置为有条件中断(或只是传递)。

您是否尝试在调试中使用断言?调试器将在代码中的某一点启动:

例如:System.Diagnostics.Debug.Assert(myValue>=0)

这里有一个以前的StackOverflow问题,它似乎就是您要寻找的:

引用该链接的答案:

Foreach用于迭代实现IEnumerable的集合。 它通过调用集合上的GetEnumerator来实现这一点,这将 返回一个枚举数

此枚举数有一个方法和一个属性:

  • MoveNext()
  • 当前
Current返回枚举器当前所在的对象,MoveNext 将当前对象更新到下一个对象

显然,指数的概念与指数的概念是不同的 枚举,并且无法执行

因此,大多数集合都可以使用 索引器和for循环构造

与其他方法相比,我更喜欢在这种情况下使用for循环 使用局部变量跟踪索引


如果迭代的任何对象都支持IndexOf()方法,则不必设置调试变量

如本例所示:

foreach (var i in myList)
{
    reportprogress(myList, i);

    //Do stuff
}

private void reportprogress<T>(List<T> l, T i)
{
    progressBar1.Value = ((l.IndexOf(i)) * 100) / l.Count;
    Application.DoEvents();
}
foreach(myList中的变量i)
{
报告进展(myList,i);
//做事
}
私有无效报告进度(列表l,T i)
{
progressBar1.值=((l.IndexOf(i))*100)/l.计数;
Application.DoEvents();
}

六年后于2017年2月更新——下面提到的扩展现在被称为。该功能现在被调用,但仅在VS2013中受支持

我还觉得这可能是一个非常有用的特性,所以我创建了它,作为我为VisualStudio调试体验所做的商业扩展的一部分,名为BugAid

当您在foreach循环中时,扩展将准确地显示您所处的迭代:

当您单击“Iteration x of y”按钮时,您将看到一个新窗口,显示项目的完整列表,并突出显示循环中的当前位置(仅当在调试器中评估集合不会产生任何副作用时,才会显示此列表)

打开Foreach可视化窗口后,您甚至可以右键单击任何即将出现的项目并选择“跳到项目”,向前运行,直到点击该项目为止(这样可以避免手动设置和干扰点击次数断点):


扩展加罗·耶里亚扎里安的答案

一种快速而肮脏的方法,无需重新编译。示例代码:

    var ints = new[] {5, 6, 0, 1};

    foreach (var i in ints)
    {
        Debug.WriteLine(100 / i);
    }
在循环之前添加一个断点,在循环内部添加一个断点。当第一次命中并且要开始计数时,设置命中计数条件:

设置一些较大的命中计数条件,重置计数器并继续。然后,当异常或其他异常触发时,您可以再次检查“当前命中计数”


假设您的代码是

foreach (String line in lines){
    Console.WriteLine(line);//breakpoint here
}

foreach
循环中放置一个断点,启动“立即窗口”,并执行以下代码
Array.IndexOf(行,行)

您还可以使用Visual Studio的即时窗口,该窗口允许您在调试时针对范围内的任何变量编写C#表达式。使用List.IndexOf()方法,如下所示:


以下是我在VS 2017中的做法:

  • 在foreach循环内设置断点
  • 右键单击断点并选择“操作”
  • 在文本框中,输入以下内容:
    $FUNCTION{list.Items.IndexOf(item)}
    其中“list”是列表的名称,“item”是当前项
  • 继续运行代码并观察输出窗口

  • Visual Studio 2017的点击率:

  • foreach
    循环中的任意位置设置断点
  • 右键单击断点并单击“条件…”
  • 选中“条件”框,将下拉菜单切换到“点击次数”,并编辑点击次数设置
  • 暂停时,将断点悬停以查看您的设置和到目前为止达到的命中率

  • foreach
    转换为
    for
    和索引需要两秒钟。有什么大不了的?@Josh-用命中率设置断点也需要2秒钟。调试器是我们的朋友,我们需要学习如何使用它。@kirk,在你意识到你应该首先使用索引变量之前,你要浪费多少次两秒钟?@Josh,如果你想在调试器中确定索引的话,你是否真的建议一个分类避免使用<代码>前缀循环?我可能已经处于耗时的运行当中,在这种情况下,我必须重新开始,这将需要2秒多的时间。我怎么从来没有听说过这个分机!!!????如果它的表现和它看起来一样好,它绝对会出现在我的“购买”名单上!谢谢:)您可能没有听说过,因为我们昨天刚刚发布了这些功能;)。我们仍处于测试阶段,请让我们知道您遇到的任何问题@奥默拉维夫:你现在提到的扩展名是OzCode吗?你可能想更新你的旧李