如何知道枚举器是否已在C#中到达集合的末尾?

时间:2010-04-26 14:14:34

标签: c# c++ collections containers porting

我正在将一个库从C ++移植到C#。旧库使用C ++中的向量,在C#中我使用泛型字典,因为它们实际上是我正在做的一个很好的数据结构(每个元素都有一个ID,然后我只使用TypeDictionary = Dictionary<String, Type>;)。现在,在C#代码中,我使用像这样的循环

TypeDictionary.Enumerator tdEnum = MyTypeDictionary.GetEnumerator();

while( tdEnum.MoveNext() ) 
{
   Type element = typeElement.Current.Value;

   // More code here
}

遍历集合的元素。问题是,在特殊情况下,我需要检查某个枚举器是否已到达集合的末尾,在C ++中我会做一个这样的检查:

if ( tdEnum == MyTypeDictionary.end() ) // More code here

但我只是不知道如何在C#中处理这种情况,有什么想法吗?

谢谢你 托马索

5 个答案:

答案 0 :(得分:12)

这是实现这一目标的一种非常简单的方法。

bool hasNext = tdEnum.MoveNext();
while (hasNext) {
    int i = tdEnum.Current;
    hasNext = tdEnum.MoveNext();
}

我找到了一个在线教程,也可以帮助您了解其工作原理。

http://www.c-sharpcorner.com/UploadFile/prasadh/Enumerators11132005232321PM/Enumerators.aspx

答案 1 :(得分:4)

MoveNext()返回false时,您知道自己处于迭代器的末尾。否则,您需要升级到更具描述性的数据结构,例如IList<T>

答案 2 :(得分:4)

我在MiscUtil中有一个“智能迭代器”类,你可能觉得它很有用。它允许您测试当前是否正在查看序列的开头或结尾以及序列中的索引。有关详细信息,请参阅usage page

当然,在大多数情况下,您可以使用MoveNext()的结果手动完成此操作,但有时额外的封装会派上用场。

请注意,根据需要,此迭代器实际上会消耗一个比它产生的值多一个的值,以便知道它是否到达终点。在大多数情况下,这不是问题,但在调试时偶尔会有一些奇怪的经历。

答案 3 :(得分:2)

如果枚举器已结束,则使用装饰器模式来保存值是一种有效的方法。 由于它实现了IEnumerator,因此您无法在代码中找到替换它的困难。

这是一个测试类:

using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MyDictionary = System.Collections.Generic.Dictionary<int, string>;
using MyKeyValue = System.Collections.Generic.KeyValuePair<int, string>;

namespace TestEnumerator
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestingMyEnumeradorPlus()
        {
            var itens = new MyDictionary()
            {
                { 1, "aaa" }, 
                { 2, "bbb" }
            };
            var enumerator = new EnumeradorPlus<MyKeyValue>(itens.GetEnumerator());
            enumerator.MoveNext();
            Assert.IsFalse(enumerator.Ended);
            enumerator.MoveNext();
            Assert.IsFalse(enumerator.Ended);
            enumerator.MoveNext();
            Assert.IsTrue(enumerator.Ended);
        }
    }

    public class EnumeradorPlus<T> : IEnumerator<T>
    {
        private IEnumerator<T> _internal;
        private bool _hasEnded = false;

        public EnumeradorPlus(IEnumerator<T> enumerator)
        {
            _internal = enumerator;
        }

        public T Current
        {
            get { return _internal.Current; }
        }

        public void Dispose()
        {
            _internal.Dispose();
        }

        object System.Collections.IEnumerator.Current
        {
            get { return _internal.Current; }
        }

        public bool MoveNext()
        {
            bool moved = _internal.MoveNext();
            if (!moved)
                _hasEnded = true;
            return moved;
        }

        public void Reset()
        {
            _internal.Reset();
            _hasEnded = false;
        }

        public bool Ended
        {
            get { return _hasEnded; }
        }
    }
}

答案 4 :(得分:1)

来自C ++,您可能无法了解C#语法。也许你可以简单地使用foreach结构来避免测试。对于字典中的每个元素,将执行以下代码:

foreach (var element in MyTypeDictionary)
{
    // More code here
}