2

The following code snippet shows an iterator from the std::vector C++ lib. What is the C# equivalent to this? Can I simply loop through each item in the vector considering its not a linked list? What exactly is the iterator doing here and how can I do the equivalent in C#? The full code is here.

 std::vector<KMeanCluster>::iterator closest_cluster = clusters.begin();

    // Figure out which cluster this color is closest to in RGB space.
    for (std::vector<KMeanCluster>::iterator cluster = clusters.begin();
        cluster != clusters.end(); ++cluster) {
      uint distance_sqr = cluster->GetDistanceSqr(r, g, b);

      if (distance_sqr < distance_sqr_to_closest_cluster) {
        distance_sqr_to_closest_cluster = distance_sqr;
        closest_cluster = cluster;
      }
    }
4

5 回答 5

6

C++ 标准库迭代器的定义方式类似于遍历集合的指针。在 C# 中,每个实现IEnumerable的集合都可以foreach循环迭代。除此之外,您仍然可以使用 s 在 C# 中执行类似于 C++ 迭代器的操作Enumerator(这在大多数情况下会使事情变得更加困难):

IEnumerable<int> myCollection = new List<int> { 1, 2, 3 };
var enumerator = myCollection.GetEnumerator();
while(enumerator.MoveNext())
    Console.WriteLine(enumerator.Current);

实际上,上面是foreach循环如何遍历引擎盖下的集合。

foreach(int num in myCollection)
    Console.WriteLine(num);

因此,就您的代码而言,这是确切的(但难以编码和理解)等价物:

IEnumerator<KMeanCluster> closest_cluster = clusters.GetEnumerator();
while (closest_cluster.MoveNext())
{
    uint distance_sqr = closest_cluster.Current.GetDistanceSqr(r, g, b);
    if (distance_sqr < distance_sqr_to_closest_cluster)
    {
        distance_sqr_to_closest_cluster = distance_sqr;
        closest_cluster = cluster;
    }
}

这是最简单的等价物:

foreach(KMeanCluster closest_cluster in clusters)
{
    uint distance_sqr = closest_cluster.GetDistanceSqr(r, g, b);
    if (distance_sqr < distance_sqr_to_closest_cluster)
    {
        distance_sqr_to_closest_cluster = distance_sqr;
        closest_cluster = cluster;
    }
}
于 2013-04-18T12:35:11.607 回答
2

迭代器基本上是一个允许对容器进行串行、非随机访问的对象。无论如何:您可以在 C# 中使用普通循环。foreach 循环在语法上更接近 C++ 原始语法

于 2013-04-18T12:27:10.613 回答
2

在 C# 中,这可能看起来像:

var closest_cluster = clusters.FirstOrDefault();
foreach (var cluster in clusters)
{
    uint distance_sqr = cluster.GetDistanceSqr(r, g, b);
    if (distance_sqr < distance_sqr_to_closest_cluster)
    {
        distance_sqr_to_closest_cluster = distance_sqr;
        closest_cluster = cluster;
    }
}

foreach运算符所做的是它在下面的用途,这IEnumerator相当于您的迭代器。

于 2013-04-18T12:28:01.247 回答
2

通用集合 -IEnumerator<T>

支持对泛型集合的简单迭代。

非通用集合 -IEnumerator

支持对非泛型集合的简单迭代。

这些是接口,应该被继承和覆盖。MoveNext和 等方法Reset。然后您可以在循环中使用该类。

于 2013-04-18T12:29:16.410 回答
1

C# 中有一个iterator构造,但在这种情况下,您不需要直接访问它,而是使用foreach循环。代码可能看起来像这样。

Cluster closestCluster = clusters.firstOrDefault();

foreach (Cluster currentCluster in clusters)
{
   //Distance logic
   if (distanceSqr < distanceSqrToClosestCluster)
   {
        closestCluster = currentCluster;
   }
}

在内部通过接口foreach访问迭代器IEnumerable<Cluster>

于 2013-04-18T12:31:43.720 回答