Ручная итерация по выбору элементов XML (C #, XDocument) - PullRequest
3 голосов
/ 28 апреля 2010

Каков наилучший способ ручной итерации (т. Е. По одному с кнопкой «Далее») над набором элементов XE в моем XDocument? Скажем, я выбираю набор элементов, который хочу таким образом:

var elems = from XElement el in m_xDoc.Descendants()
            where (el.Name.LocalName.ToString() == "q_a") 
            select el;

Я могу использовать IEnumerator для итерации по ним, т.е. IEnumerator m_iter;

Но когда я добираюсь до конца и хочу перейти к началу, если я вызову Reset () для него, он генерирует исключение NotSupportedException. Это потому, что, как указано в спецификации Microsoft C # 2.0 в главе 22 «Итераторы»: « Обратите внимание, что объекты перечислителя не поддерживают метод IEnumerator.Reset. При вызове этого метода создается исключение System.NotSupportedException ."

Так каков правильный способ сделать это? А что, если я также хочу иметь двунаправленную итерацию, то есть кнопку «назад» тоже?

Кто-то на дискуссионном форуме Microsoft сказал, что в любом случае я не должен использовать IEnumerable напрямую. Он сказал, что есть способ сделать то, что я хочу с LINQ, но я не понимаю, что. Кто-то еще предложил добавить XElements в список с помощью ToList (), что, я думаю, сработает, но я не был уверен, что это «лучшая практика». Заранее спасибо за любые предложения!

Ответы [ 2 ]

1 голос
/ 28 апреля 2010

очень редко вам нужно использовать перечислитель напрямую;просто используйте foreach на elems.Вот итерация дважды:

// first time
foreach(var item in elems) {...}
// second time
foreach(var item in elems) {...}

Нет необходимости в Reset() - для вас просто используется GetEnumerator() дважды , что является правильным способом сделать это.Если вы не можете выполнить запрос дважды по какой-либо причине или хотите использовать произвольный доступ, а не последовательный, то вам придется его буферизовать - возможно, в список с ToList().

1 голос
/ 28 апреля 2010

Решение очень простое. Просто создайте список из вашей коллекции XElements.

var elems = (from XElement el in m_xDoc.Descendants()
            where (el.Name.LocalName.ToString() == "q_a") 
            select el).ToList();

Вы можете перечислить его через индексатор elems[i] и переходить назад и вперед. Просто сохраните текущий индекс в переменной и уменьшите / увеличьте его нажатием кнопки (с циклическим изменением).

xml, который вы анализируете по запросу по вашему запросу linq (см. MSDN для отложенное выполнение и отложенная оценка в Linq to XML ) Даже если он будет поддерживать IEnumerable.Reset(), ему придется каждый раз анализировать его снова. Если вы вызываете .ToList<T>(), он анализирует все элементы-потомки один раз и загружает их в память.

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