Может ли отладчик подсказать мне количество / состояние цикла foreach? - PullRequest
8 голосов
/ 10 июня 2011

Предположим, у меня есть следующий код:

List<SomeObject> someObjects = ReturnListWithThousandsOfObjects();

foreach(SomeObject someobject in someObjects)
{
   DoSomething.With(someObject);
}

А также предположим, что после минуты работы я установил точку останова на DoSomething.With(someObject);.

Отладчик ломается для меня просто отлично. Но теперь я хочу знать, в какой момент я нахожусь в своей итерации списка (предположим, что список неупорядочен / не имеет ключа).

Может ли отладчик сказать, что "foreach выполнил 532 из 2321 итерации"?

Ответы [ 6 ]

9 голосов
/ 10 июня 2011

Как отладочная, не существует ли метод indexof?

т.е.

quickwatch - someObjects.indexOf (someObject);

Добавлено - Извините, если немного кратко.

Как указывает Guffa, это будет работать лучше всего, если значения уникальны или функция сравнения по умолчанию для равенства Функция EqualityComparer использует уникальное значение (например, пользовательская перегрузка GetHashCode / Equals).

    public class ATest
    {
        public int number { get; set; }
        public int boo { get; set; }
        public ATest()
        {

        }
    }

    protected void Go()
    {
        List<ATest> list = new List<ATest>();

        foreach(var i in Enumerable.Range(0,30)) {
            foreach(var j in Enumerable.Range(0,100)) {
                list.Add(new ATest() { number = i, boo = j });                  
            }
        }

        var o =0; //only for proving concept.
        foreach (ATest aTest in list)
        {               
            DoSomthing(aTest);
            //proof that this does work in this example.
            o++;
            System.Diagnostics.Debug.Assert(o == list.IndexOf(aTest));
        }

    }
5 голосов
/ 10 июня 2011

Это для Visual Studio, но в других IDE должно быть что-то похожее:

Когда вы устанавливаете точку останова, вы можете щелкнуть по ней правой кнопкой мыши и перейти к «Счетчику посещений» Вы можете настроить некоторые параметры там («больше или равно» 0 заставит его работать как обычная точка останова - так будет «всегда ломаться»). Интересной частью является поле Hit Count (которое можно сбросить).

Это может решить часть "количество итераций". Для общего количества, я боюсь, вам придется найти его самостоятельно, при условии, что у используемой вами коллекции такой номер легко доступен.

Вы также можете установить точку останова на срабатывание после очень большого числа попаданий, скажем, нескольких тысяч / миллионов (я не знаю, каков их предел). Затем, когда срабатывает «реальная» точка останова, та, где вы хотите узнать, сколько раз была достигнута исходная точка останова, вы можете просто проверить ее и при необходимости сбросить.

2 голосов
/ 10 июня 2011

В этом случае, если вы действительно хотите узнать, что это за счет, разве вы не используете цикл for?

List<SomeObject> someObjects = ReturnListWithThousandsOfObjects();


for(int someObj= 1; someObj <= someObjects.Count; someObj++)
{
   Console.WriteLine(string.Format("{0} of {1} iterations", someObj, someObjects.Count));
   DoSomething.With(someObject[someObj]);
}

Реальной разницы в производительности между циклами foreach и for не будет, поэтому цикл for станет лучшей альтернативой для ситуации, которую вы хотите достичь.

1 голос
/ 10 июня 2011

Если вы не ведете счет в переменной вручную, вы не сможете легко определить это. Поскольку цикл повторяется в вашей коллекции, он просто использует перечислитель, чтобы получить следующий элемент в коллекции, чтобы сообщить, что больше нет элементов, в которые он выходит.

Чтобы вручную вести подсчет, вы просто должны сделать:

int count = 0;
List<SomeObject> someObjects = ReturnListWithThousandsOfObjects();

foreach(SomeObject someobject in someObjects)
{
     count++;
     DoSomething.With(someObject);
}

Теперь в любой момент вы можете приостановить выполнение и посмотреть, на какой итерации вы находитесь

0 голосов
/ 06 февраля 2019

Да, может.Вот как [в VS 2017]:

  1. Установить точку останова внутри цикла foreach
  2. Щелкните правой кнопкой мыши точку останова и выберите «Действия»
  3. В текстевведите следующее: $FUNCTION {list.Items.IndexOf(item)} где «список» - это имя вашего списка, а «элемент» - текущий элемент
  4. Продолжите выполнение кода и посмотрите окно вывода
0 голосов
/ 20 апреля 2017

Создайте метод расширения в List и List, который принимает Action fold, Action sideFold, который позволяет вам накапливать побочные эффекты, такие как проверка на наличие отладчика и нарушение состояния накопления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...