Matt
Matt

Reputation: 26971

Debugging a foreach loop in C#: what iteration is this?

Other than setting a debug variable and incrementing it every time you start the foreach, when you break in with the Visual Studio debugger connected, is there a way to tell that this is the Xth time through the loop?

I guess this would be a feature of Visual Studio if anything, not something that would be added to the compiled code.

Upvotes: 48

Views: 24473

Answers (11)

Kim Homann
Kim Homann

Reputation: 3229

Hit count in Visual Studio 2017:

  1. Set the breakpoint anywhere inside the foreach loop.
  2. Right-click your breakpoint and click "Conditions...".

Conditions

  1. Check "Conditions" box, switch dropdown to "Hit Count" and edit your Hit Count settings.

Hit Count

  1. On halt, hover the breakpoint to see your settings and the Hit Count reached so far.

Hover

  1. Don't forget that your hit count is not automatically reset to zero when you enter the loop for the 2nd time in the same session. ;-) But you can reset it manually:

Reset

Upvotes: 5

brandonstrong
brandonstrong

Reputation: 688

Here's how I do it [in VS 2017] :

  1. Set a break point inside the foreach loop
  2. Right click the break point and select 'Actions'
  3. In the text box, enter the following: $FUNCTION {list.Items.IndexOf(item)} where 'list' is the name of your list and 'item' is the current item
  4. Continue running the code and watch the output window

Upvotes: 4

Jeremy Deal
Jeremy Deal

Reputation: 468

You can also use Visual Studio's Immediate Window, which allows you to write C# expressions against any variables in scope while debugging. Use the List.IndexOf() method, like so:

querying the foreach iteration index in the Immediate Window

Upvotes: 30

user961954
user961954

Reputation: 3214

Let's say your code is

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

Put a breakpoint inside foreach loop, launch "Immediate window" and execute following code Array.IndexOf(lines, line);

Upvotes: 3

Omer Raviv
Omer Raviv

Reputation: 11827

Update Feb 2017, six years later - the extension mentioned below is now called OzCode. The feature is now called Foresee, but is only supported in VS2013.

I also felt that this could be a very useful feature, so I created it as part of a commercial extension I made for the Visual Studio debugging experience called BugAid.

The extension shows you exactly which iteration you are whenever you are inside a foreach loop: Foreach Buttons

When you click the "Iteration x of y" button, you'll see a new window, showing the complete list of items, with the your current location in the loop highlighted (this list is only shown if evaluating the collection in the debugger does not cause any side effects).

Once you open ths Foreach Visualization window, you can even right click any of the upcoming items and choose "Skip to Item", to run forward until you hit that item (this can save you from manually setting-up and messing with hit-count breakpoint):

Using Skip To Iteratioon

Upvotes: 4

Luiscencio
Luiscencio

Reputation: 3965

If whatever you are iterating supports the IndexOf() method, you don't have to set a debug variable.

Like in this example:

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();
}

Upvotes: 1

jumpdart
jumpdart

Reputation: 1712

Heres a previous Stack Overflow question that seems to be what your looking for: get-index-of-current-foreach-iteration

Answer quoted from that link:

Foreach is for iterating over collections that implement IEnumerable. It does this by calling GetEnumerator on the collection, which will return an Enumerator.

This Enumerator has a method and a property:

  • MoveNext()
  • Current

Current returns the object that Enumerator is currently on, MoveNext updates Current to the next object.

Obviously, the concept of an index is foreign to the concept of enumeration, and cannot be done.

Because of that, most collections are able to be traversed using an indexer and the for loop construct.

I greatly prefer using a for loop in this situation compared to tracking the index with a local variable.

Upvotes: 11

johv
johv

Reputation: 4594

Expanding on Garo Yeriazarian's answer...

A quick and dirty way without recompiling. Example code:

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

    foreach (var i in ints)
    {
        Debug.WriteLine(100 / i);
    }

Add one breakpoint before the loop and one inside it. When the first is hit and you want to start counting, set a Hit Count condition:

two breakpoints

Set some large hit count condition and reset the counter and continue. Then when the exception or whatever fires, you can check the "Current hit count" again.

Hit count dialog

Upvotes: 15

user353283
user353283

Reputation:

Have you tried using assertion in debugging? The debugger will be launched at that exact point in your code:
For example: System.Diagnostics.Debug.Assert (myValue >=0)

Upvotes: 2

Garo Yeriazarian
Garo Yeriazarian

Reputation: 2533

Set a breakpoint inside the loop, then right click on the breakpoint to set the conditions. You can also right click to see the hit count while debugging and reset it if you want. You can set a boolean expression that is evaluated when the breakpoint hits to conditionally break (or just pass over).

Upvotes: 26

Incognito
Incognito

Reputation: 16577

May be you can use breakpoint hit count. Not exactly what you want, but may be helpful.

Also is there any serious reason why you don't want to use for loop in this case.

Upvotes: 5

Related Questions