简体   繁体   English

HashSet 枚举器有什么作用?

[英]What does a HashSet Enumerator do?

I'm not used to write C# code, only Java and Python.我不习惯写C#代码,只会写Java和Python。 Now I found some code example for an algorithm which is only available in C#.现在我找到了一些仅在 C# 中可用的算法的代码示例。 There is one structure I don't understand, it is the Enumerator.有一个我不明白的结构,它是枚举器。

HashSet<Node>.Enumerator enumerator = hashSet.GetEnumerator();
enumerator.MoveNext();
Item next = enumerator.Current;

So Item is the data type stored in the HashSet hashSet .所以Item是存储在 HashSet hashSet中的数据类型。 Is this equal to a for-loop iterating over a HashSet or how else can that be translated into python or java?这是否等于遍历 HashSet 的 for 循环,或者如何将其转换为 python 或 java?

GetEnumerator() methods are presented in some data structures in C# such as List , Set , etc. It enables doing iteration through. GetEnumerator()方法出现在 C# 中的一些数据结构中,例如ListSet等。它可以进行迭代。 Actually, foreach internally makes use of it.实际上, foreach在内部使用它。


foreach statement is to iterate through the elements of certain data structures. foreach语句是遍历某些数据结构的元素。 A foreach can be used when all of the following conditions hold:当满足以下所有条件时,可以使用foreach

  • The data structure implements either IEnumerable (which is to satisfy legacy codes before generics) or IEnumerable<T> for some type T .数据结构实现了IEnumerable (这是为了满足泛型之前的遗留代码)或IEnumerable<T>用于某些类型T
  • You do not need to know the locations in the data structure of the individual elements.您不需要知道各个元素在数据结构中的位置。

For example, the string class implements both IEnumerable and IEnumerable<Char> .例如, string class 实现了IEnumerableIEnumerable<Char>

The IEnumerable<T> interface implies the data structure requires two methods: IEnumerable<T>接口暗示数据结构需要两种方法:

  • public IEnumerator<T> GetEnumerator()
  • IEnumerator IEnumerable.GetEnumerator()

The latter method is required only because IEnumerable<T> is a subtype of IEnumerable , and that interface requires a GetEnumerator method that returns a non-generic IEnumerator .仅需要后一种方法是因为IEnumerable<T>IEnumerable的子类型,并且该接口需要返回非泛型IEnumeratorGetEnumerator方法。 Both of these methods should return the same object;这两种方法都应该返回相同的 object; hence, because IEnumerator<T> is also a subtype of IEnumerator , this method can simply call the first method:因此,因为IEnumerator<T>也是IEnumerator的子类型,所以这个方法可以简单地调用第一个方法:

System.Collections.IEnumerator IEnumerable.GetEnumerator()
{
    return GetEnumerator();
}

As you can see, the IEnumerable.GetEnumerator() method returns a reference to another interface named System.Collections.IEnumerator .如您所见, IEnumerable.GetEnumerator()方法返回对另一个名为System.Collections.IEnumerator的接口的引用。 This interface provides the infrastructure to allow the caller to traverse the internal objects contained by the IEnumerable-compatible container:该接口提供了允许调用者遍历 IEnumerable 兼容容器所包含的内部对象的基础结构:

public interface IEnumerator
{
   bool MoveNext (); // Advance the internal position of the cursor.
   object Current { get;} // Get the current item (read-only property).
   void Reset (); // Reset the cursor before the first member.
}

Let's exemplify it.让我们举例说明。

public class PowersOfThree : IEnumerable<int>
{      
    public IEnumerator<int> GetEnumerator()
    {
        return new PowersOfThreeEnumerator();
    }       
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }       
}


internal class PowersOfThreeEnumerator : IEnumerator<int>
{
    private int index = 0;

    public int Current
    {
        get { return (int)System.Math.Pow(3, index); }
    }

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

    public bool MoveNext()
    {
        index++;

        if (index > 10)
            return false;
        else
            return true;
    }

    public void Reset()
    {
        index = 0;
    }

    public void Dispose()
    {
    }
}

public class Test 
{
    public static void Main(string[] str)
    {
        var p2 = new PowersOfThree();
        foreach (int p in p2)
        {
            System.Console.WriteLine(p);
        }
    }
}

Current method returns the same element until MoveNext method is called. Current方法返回相同的元素,直到MoveNext方法。 The initial index is 0 each MoveNext method increments the index from 1 to 10, inclusively, then it returns false .初始索引为0每个MoveNext方法将索引从1递增到 10(含),然后返回false When the enumerator is at this position, subsequent calls to MoveNext also return false .当枚举器位于此 position 时,对MoveNext的后续调用也返回false

Do you see that what happened to Current when MoveNext returned false ?您是否看到当MoveNext返回falseCurrent发生了什么? Can you set Current to the first element of the collection again?您可以再次将Current设置为集合的第一个元素吗? If you don't reinstantiate new enumerator, no.如果您不重新实例化新的枚举器,则不会。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM